From 3c28e0f920f605ca775e3a91e0a7c4ccb91d82e5 Mon Sep 17 00:00:00 2001 From: toniocodo Date: Tue, 9 Jul 2024 19:53:26 +0200 Subject: [PATCH 01/33] feat adapt oeth redeem routes, request screen, update vault abi --- apps/defi/src/routes.ts | 3 +- libs/defi/oeth/src/redeem/actions/arm.ts | 100 ++ libs/defi/oeth/src/redeem/actions/index.ts | 14 + .../src/redeem/actions/redeemVaultAsync.ts | 134 ++ .../redeem/components/RedeemActionCard.tsx | 216 ++- .../oeth/src/redeem/components/Swapper.tsx | 44 +- .../oeth/src/redeem/components/ViewSwitch.tsx | 48 + libs/defi/oeth/src/redeem/constants.ts | 29 +- libs/defi/oeth/src/redeem/hooks.ts | 22 + libs/defi/oeth/src/redeem/index.ts | 2 +- libs/defi/oeth/src/redeem/routes.tsx | 24 - libs/defi/oeth/src/redeem/types.ts | 16 +- .../defi/oeth/src/redeem/views/RedeemView.tsx | 49 +- libs/shared/contracts/abi-json/OETHVault.json | 1398 ++++++++++++++++- libs/shared/contracts/src/abis/OETHVault.ts | 1225 +++++++++++++-- libs/shared/contracts/src/contracts.ts | 3 +- libs/shared/icons/src/protocols/arm.svg | 17 + libs/shared/icons/src/protocols/index.tsx | 4 + 18 files changed, 2996 insertions(+), 352 deletions(-) create mode 100644 libs/defi/oeth/src/redeem/actions/arm.ts create mode 100644 libs/defi/oeth/src/redeem/actions/redeemVaultAsync.ts create mode 100644 libs/defi/oeth/src/redeem/components/ViewSwitch.tsx create mode 100644 libs/defi/oeth/src/redeem/hooks.ts delete mode 100644 libs/defi/oeth/src/redeem/routes.tsx create mode 100644 libs/shared/icons/src/protocols/arm.svg diff --git a/apps/defi/src/routes.ts b/apps/defi/src/routes.ts index e1939fa91..27adf0192 100644 --- a/apps/defi/src/routes.ts +++ b/apps/defi/src/routes.ts @@ -49,7 +49,8 @@ export const routes: RouteObject[] = [ }, }, { - ...oeth.oethRedeemRoute, + path: 'redeem', + Component: oeth.RedeemView, handle: { title: defineMessage({ defaultMessage: 'Redeem' }), icon: FaArrowDownFromArcRegular, diff --git a/libs/defi/oeth/src/redeem/actions/arm.ts b/libs/defi/oeth/src/redeem/actions/arm.ts new file mode 100644 index 000000000..7831d9b24 --- /dev/null +++ b/libs/defi/oeth/src/redeem/actions/arm.ts @@ -0,0 +1,100 @@ +import { formatUnits, maxUint256 } from 'viem'; + +import type { + Allowance, + Approve, + EstimateApprovalGas, + EstimateGas, + EstimateRoute, + IsRouteAvailable, + Swap, +} from '@origin/shared/providers'; +import type { EstimateAmount } from '@origin/shared/providers'; + +const isRouteAvailable: IsRouteAvailable = async ( + config, + { tokenIn, amountIn }, +) => { + return false; +}; + +const estimateAmount: EstimateAmount = async (config, { amountIn }) => { + return amountIn; +}; + +const estimateGas: EstimateGas = async (config, { tokenIn, amountIn }) => { + return 0n; +}; + +const allowance: Allowance = async (config, { tokenIn }) => { + return maxUint256; +}; + +const estimateApprovalGas: EstimateApprovalGas = async ( + config, + { tokenIn, amountIn }, +) => { + return 0n; +}; + +const estimateRoute: EstimateRoute = async ( + config, + { tokenIn, tokenOut, amountIn, route, slippage }, +) => { + if (amountIn === 0n) { + return { + ...route, + estimatedAmount: 0n, + gas: 0n, + rate: 0, + allowanceAmount: 0n, + approvalGas: 0n, + }; + } + + const [estimatedAmount, allowanceAmount, approvalGas, gas] = + await Promise.all([ + estimateAmount(config, { tokenIn, tokenOut, amountIn }), + allowance(config, { tokenIn, tokenOut }), + estimateApprovalGas(config, { amountIn, tokenIn, tokenOut }), + estimateGas(config, { + tokenIn, + tokenOut, + amountIn, + slippage, + }), + ]); + + return { + ...route, + estimatedAmount, + gas, + approvalGas, + allowanceAmount, + rate: + +formatUnits(estimatedAmount, tokenOut.decimals) / + +formatUnits(amountIn, tokenIn.decimals), + }; +}; + +const approve: Approve = async (config, { tokenIn, tokenOut, amountIn }) => { + return null; +}; + +const swap: Swap = async ( + config, + { tokenIn, tokenOut, amountIn, slippage, amountOut }, +) => { + return null; +}; + +export default { + isRouteAvailable, + estimateAmount, + estimateGas, + estimateRoute, + allowance, + estimateApprovalGas, + approve, + swap, +}; diff --git a/libs/defi/oeth/src/redeem/actions/index.ts b/libs/defi/oeth/src/redeem/actions/index.ts index 68d0e5a0d..b3a55397c 100644 --- a/libs/defi/oeth/src/redeem/actions/index.ts +++ b/libs/defi/oeth/src/redeem/actions/index.ts @@ -1,6 +1,8 @@ import { defineMessage } from 'react-intl'; +import arm from './arm'; import redeemVault from './redeemVault'; +import redeemVaultAsync from './redeemVaultAsync'; import swapCurve from './swapCurve'; import type { SwapApi } from '@origin/shared/providers'; @@ -66,4 +68,16 @@ export const redeemActions: Record = { routeLabel: defineMessage({ defaultMessage: 'Redeem via OETH Vault' }), buttonLabel: defineMessage({ defaultMessage: 'Redeem' }), }, + arm: { + ...defaultApi, + ...arm, + routeLabel: defineMessage({ defaultMessage: 'Redeem via the ARM' }), + buttonLabel: defineMessage({ defaultMessage: 'Redeem' }), + }, + 'redeem-vault-async': { + ...defaultApi, + ...redeemVaultAsync, + routeLabel: defineMessage({ defaultMessage: 'Redeem via OETH Vault' }), + buttonLabel: defineMessage({ defaultMessage: 'Redeem' }), + }, }; diff --git a/libs/defi/oeth/src/redeem/actions/redeemVaultAsync.ts b/libs/defi/oeth/src/redeem/actions/redeemVaultAsync.ts new file mode 100644 index 000000000..969febd9f --- /dev/null +++ b/libs/defi/oeth/src/redeem/actions/redeemVaultAsync.ts @@ -0,0 +1,134 @@ +import { contracts, whales } from '@origin/shared/contracts'; +import { simulateContractWithTxTracker } from '@origin/shared/providers'; +import { isNilOrEmpty } from '@origin/shared/utils'; +import { getAccount, getPublicClient, writeContract } from '@wagmi/core'; +import { formatUnits, maxUint256 } from 'viem'; + +import type { + Allowance, + Approve, + EstimateApprovalGas, + EstimateGas, + EstimateRoute, + IsRouteAvailable, + Swap, +} from '@origin/shared/providers'; +import type { EstimateAmount } from '@origin/shared/providers'; + +const isRouteAvailable: IsRouteAvailable = async ( + config, + { tokenIn, amountIn }, +) => { + return true; +}; + +const estimateAmount: EstimateAmount = async (config, { amountIn }) => { + return amountIn; +}; + +const estimateGas: EstimateGas = async (config, { tokenIn, amountIn }) => { + const publicClient = getPublicClient(config); + + if (amountIn === 0n || !publicClient || !tokenIn?.address) { + return 0n; + } + + let requestGasEstimate = 0n; + try { + requestGasEstimate = await publicClient.estimateContractGas({ + address: contracts.mainnet.OETHVault.address, + abi: contracts.mainnet.OETHVault.abi, + functionName: 'requestWithdrawal', + args: [amountIn], + account: whales.mainnet.OETH, + }); + } catch { + requestGasEstimate = 161_000n; + } + + return requestGasEstimate + 113_010n; +}; + +const allowance: Allowance = async (config, { tokenIn }) => { + return maxUint256; +}; + +const estimateApprovalGas: EstimateApprovalGas = async ( + config, + { tokenIn, amountIn }, +) => { + return 0n; +}; + +const estimateRoute: EstimateRoute = async ( + config, + { tokenIn, tokenOut, amountIn, route, slippage }, +) => { + if (amountIn === 0n) { + return { + ...route, + estimatedAmount: 0n, + gas: 0n, + rate: 0, + allowanceAmount: 0n, + approvalGas: 0n, + }; + } + + const [estimatedAmount, allowanceAmount, approvalGas, gas] = + await Promise.all([ + estimateAmount(config, { tokenIn, tokenOut, amountIn }), + allowance(config, { tokenIn, tokenOut }), + estimateApprovalGas(config, { amountIn, tokenIn, tokenOut }), + estimateGas(config, { + tokenIn, + tokenOut, + amountIn, + slippage, + }), + ]); + + return { + ...route, + estimatedAmount, + gas, + approvalGas, + allowanceAmount, + rate: + +formatUnits(estimatedAmount, tokenOut.decimals) / + +formatUnits(amountIn, tokenIn.decimals), + }; +}; + +const approve: Approve = async (config, { tokenIn, tokenOut, amountIn }) => { + return null; +}; + +const swap: Swap = async (config, { amountIn }) => { + const { address } = getAccount(config); + + if (amountIn === 0n || isNilOrEmpty(address)) { + return null; + } + + const { request } = await simulateContractWithTxTracker(config, { + address: contracts.mainnet.OETHVault.address, + abi: contracts.mainnet.OETHVault.abi, + functionName: 'requestWithdrawal', + args: [amountIn], + }); + const hash = await writeContract(config, request); + + return hash; +}; + +export default { + isRouteAvailable, + estimateAmount, + estimateGas, + estimateRoute, + allowance, + estimateApprovalGas, + approve, + swap, +}; diff --git a/libs/defi/oeth/src/redeem/components/RedeemActionCard.tsx b/libs/defi/oeth/src/redeem/components/RedeemActionCard.tsx index 23113e3cb..91e6d7e69 100644 --- a/libs/defi/oeth/src/redeem/components/RedeemActionCard.tsx +++ b/libs/defi/oeth/src/redeem/components/RedeemActionCard.tsx @@ -1,22 +1,20 @@ -import { Card, Stack, Typography } from '@mui/material'; +import { alpha, Card, Stack, SvgIcon, Typography } from '@mui/material'; import { ValueLabel } from '@origin/shared/components'; -import { Curve, Origin } from '@origin/shared/icons'; +import { OETH } from '@origin/shared/icons'; import { routeEq, - useGasPrice, useHandleSelectSwapRoute, useIsSwapRouteAvailable, - useSwapRouteAllowance, useSwapState, } from '@origin/shared/providers'; -import { isNilOrEmpty } from '@origin/shared/utils'; -import { add, format, from } from 'dnum'; +import { format, from } from 'dnum'; import { useIntl } from 'react-intl'; import type { CardProps, TypographyProps } from '@mui/material'; import type { ValueLabelProps } from '@origin/shared/components'; +import type { EstimatedSwapRoute, SwapRoute } from '@origin/shared/providers'; -import type { OethRedeemAction } from '../types'; +import type { Meta, OethRedeemAction } from '../types'; export type RedeemActionCardProps = { action: OethRedeemAction; @@ -33,88 +31,83 @@ export const RedeemActionCard = ({ tokenIn, tokenOut, isSwapRoutesLoading, - swapRoutes, - swapActions, selectedSwapRoute, estimatedSwapRoutes, + swapRoutes, + swapActions, }, ] = useSwapState(); const handleSelectSwapRoute = useHandleSelectSwapRoute(); - const route = swapRoutes.find((r) => routeEq({ tokenIn, tokenOut, action }, r), ); - const estimatedRoute = estimatedSwapRoutes.find((r) => routeEq(route, r)); - - const { - data: swapGasPrice, - isLoading: swapGasPriceLoading, - isFetching: swapGasPriceFetching, - } = useGasPrice(estimatedRoute?.gas, estimatedRoute?.tokenIn.chainId, { - refetchInterval: 30e3, - enabled: !!estimatedRoute && estimatedRoute?.gas > 0n, - }); - const { - data: approvalGasPrice, - isLoading: approvalGasPriceLoading, - isFetching: approvalGasPriceFetching, - } = useGasPrice( - estimatedRoute?.approvalGas, - estimatedRoute?.tokenIn.chainId, - { - refetchInterval: 30e3, - enabled: !!estimatedRoute && estimatedRoute?.approvalGas > 0n, - }, - ); - const { data: allowance } = useSwapRouteAllowance(route); const { data: isRouteAvailable, isLoading: isRouteAvailableLoading } = useIsSwapRouteAvailable(route); - - const isSelected = routeEq(selectedSwapRoute, route); - const isEmptyValue = isNilOrEmpty(estimatedRoute) || amountIn === 0n; - const isGasLoading = - isSwapRoutesLoading || - (swapGasPriceLoading && swapGasPriceFetching) || - (approvalGasPriceLoading && approvalGasPriceFetching); - const gasPrice = add( - swapGasPrice?.gasCostUsd ?? from(0), - (allowance ?? 0n) < amountIn - ? approvalGasPrice?.gasCostUsd ?? from(0) - : from(0), - ); + const estimatedRoute = estimatedSwapRoutes.find((r) => routeEq(r, route)); + const isSelected = routeEq({ tokenIn, tokenOut, action }, selectedSwapRoute); + const isEmptyValue = amountIn === 0n; + const isComingSoon = + (route as SwapRoute)?.meta?.comingSoon ?? false; const routeLabel = swapActions[action].routeLabel; - const isDisabled = !isRouteAvailableLoading && !isRouteAvailable; + const isDisabled = + isComingSoon || (!isRouteAvailableLoading && !isRouteAvailable); return ( 0n && { - cursor: 'pointer', - '&:hover': { - borderColor: 'primary.main', - }, + backgroundColor: 'background.highlight', + ...(amountIn > 0n && + !isComingSoon && { + cursor: 'pointer', + '&:hover': { + borderColor: 'primary.main', + }, + }), + ...(isSelected && { + borderColor: 'primary.main', }), - ...(isDisabled - ? { opacity: 0.5, cursor: 'default' } - : isSelected - ? { - borderColor: 'primary.main', - backgroundColor: 'background.highlight', - } - : {}), ...rest?.sx, }} role="button" onClick={() => { - if (!isDisabled && estimatedRoute && amountIn > 0n) { - handleSelectSwapRoute(estimatedRoute); + if (!isDisabled && amountIn > 0n) { + handleSelectSwapRoute(route as unknown as EstimatedSwapRoute); } }} > + {isComingSoon && ( + + alpha(theme.palette.background.highlight, 0.8), + backdropFilter: 'blur(px)', + }} + > + + theme.palette.getContrastText( + theme.palette.background.highlight, + ), + }} + > + {intl.formatMessage({ defaultMessage: 'Coming soon' })} + + + )} - {intl.formatMessage(routeLabel)} + {intl.formatMessage(routeLabel ?? { defaultMessage: 'Route' })} - {action === 'redeem-vault' ? ( - - ) : ( - - )} + )?.meta?.icon ?? OETH + } + sx={{ fontSize: 20 }} + /> - {isDisabled ? ( - - {intl.formatMessage({ - defaultMessage: 'Larger redemptions coming soon', - })} - - ) : ( - - - ) : ( - intl.formatMessage({ defaultMessage: '~1min' }) + + + ) : ( + intl.formatMessage( + (route as SwapRoute)?.meta + ?.waitTime ?? { defaultMessage: '~1 min' }, ) - } - isLoading={isSwapRoutesLoading} - /> - - ) : ( - intl.formatMessage( - { defaultMessage: '1:{rate}' }, - { - rate: format(from(estimatedRoute?.rate ?? 0), 3), - }, - ) + ) + } + isLoading={isSwapRoutesLoading} + /> + + ) : ( + intl.formatMessage( + { defaultMessage: '1:{rate}' }, + { + rate: format(from(estimatedRoute?.rate ?? 0), 3), + }, ) - } - isLoading={isSwapRoutesLoading} - /> - - ) : ( - intl.formatMessage( - { defaultMessage: '~{value}' }, - { - value: `$${format(gasPrice, 2)}`, - }, - ) - ) - } - isLoading={isGasLoading} - /> - - )} + ) + } + isLoading={isSwapRoutesLoading} + /> + ); diff --git a/libs/defi/oeth/src/redeem/components/Swapper.tsx b/libs/defi/oeth/src/redeem/components/Swapper.tsx index 411870550..76c8f2b03 100644 --- a/libs/defi/oeth/src/redeem/components/Swapper.tsx +++ b/libs/defi/oeth/src/redeem/components/Swapper.tsx @@ -11,7 +11,6 @@ import { } from '@mui/material'; import { activityOptions, - SettingsButton, TokenButton, TokenInput, useDeleteActivity, @@ -29,11 +28,11 @@ import { isNativeCurrency, SwapProvider, useDeleteNotification, + useGasPrice, useHandleAmountInChange, useHandleApprove, useHandleSwap, usePushNotification, - useSlippage, useSwapperPrices, useSwapRouteAllowance, useSwapState, @@ -43,9 +42,8 @@ import { formatError, getFormatPrecision, isNilOrEmpty, - subPercentage, } from '@origin/shared/utils'; -import { format, mul } from 'dnum'; +import { format, from, mul } from 'dnum'; import { useIntl } from 'react-intl'; import { useAccount } from 'wagmi'; @@ -255,12 +253,14 @@ function SwapperWrapped({ swapActions, }, ] = useSwapState(); - const { value: slippage } = useSlippage(); const { data: prices, isLoading: isPriceLoading } = useSwapperPrices(); const { data: allowance } = useSwapRouteAllowance(selectedSwapRoute); const { data: balTokenIn, isLoading: isBalTokenInLoading } = useWatchBalance({ token: tokenIn, }); + const { data: gasPrice, isLoading: isGasPriceLoading } = useGasPrice( + selectedSwapRoute?.gas, + ); const handleAmountInChange = useHandleAmountInChange(); const handleApprove = useHandleApprove(); const handleSwap = useHandleSwap(); @@ -273,7 +273,6 @@ function SwapperWrapped({ estimatedAmount, prices?.[getTokenPriceKey(tokenOut)] ?? 0, ); - const minReceived = subPercentage(amountOutUsd, slippage); const needsApproval = isConnected && amountIn > 0n && @@ -317,14 +316,13 @@ function SwapperWrapped({ } /> - {intl.formatMessage({ defaultMessage: 'Redeem amount' })} + {intl.formatMessage({ defaultMessage: 'Amount' })} - {intl.formatMessage({ defaultMessage: 'Route' })} + {intl.formatMessage({ defaultMessage: 'Instant or async' })} - - + + {intl.formatMessage({ defaultMessage: 'Receive amount' })} @@ -405,31 +403,17 @@ function SwapperWrapped({ px={1} > - {intl.formatMessage( - { - defaultMessage: - 'Minimum received with {slippage} slippage:', - }, - { - slippage: intl.formatNumber(slippage, { - style: 'percent', - minimumFractionDigits: 2, - maximumFractionDigits: 2, - }), - }, - )} + {intl.formatMessage({ + defaultMessage: 'Approximate gas cost:', + })} - $ - {format(minReceived, { - digits: getFormatPrecision(minReceived), - decimalsRounding: 'ROUND_DOWN', - })} + ${format(gasPrice?.gasCostUsd ?? from(0), 2)} diff --git a/libs/defi/oeth/src/redeem/components/ViewSwitch.tsx b/libs/defi/oeth/src/redeem/components/ViewSwitch.tsx new file mode 100644 index 000000000..c27b0eb1a --- /dev/null +++ b/libs/defi/oeth/src/redeem/components/ViewSwitch.tsx @@ -0,0 +1,48 @@ +import { Stack } from '@mui/material'; +import { SliderSwitch } from '@origin/shared/components'; +import { useIntl } from 'react-intl'; + +import { useViewSelect } from '../hooks'; + +import type { StackProps } from '@mui/material'; +import type { Option } from '@origin/shared/components'; + +export const ViewSwitch = (props: StackProps) => { + const intl = useIntl(); + const { view, update } = useViewSelect(); + + const handleChange = (newVal: string | number) => { + update(newVal as 'request' | 'claim'); + }; + + const options: Option[] = [ + { + label: intl.formatMessage({ defaultMessage: 'Request' }), + value: 'request', + }, + { label: intl.formatMessage({ defaultMessage: 'Claim' }), value: 'claim' }, + ]; + + return ( + + + `inset 0 0 0 1px ${theme.palette.background.default}`, + }} + /> + + ); +}; diff --git a/libs/defi/oeth/src/redeem/constants.ts b/libs/defi/oeth/src/redeem/constants.ts index 5414f83af..8d44f3567 100644 --- a/libs/defi/oeth/src/redeem/constants.ts +++ b/libs/defi/oeth/src/redeem/constants.ts @@ -1,20 +1,41 @@ import { tokens } from '@origin/shared/contracts'; +import { ARM, OETH } from '@origin/shared/icons'; +import { defineMessage } from 'react-intl'; import type { SwapRoute } from '@origin/shared/providers'; -import type { OethRedeemAction } from './types'; +import type { Meta, OethRedeemAction } from './types'; export const GAS_BUFFER = 10n; // 10% -export const redeemRoutes: SwapRoute[] = [ +export const redeemRoutes: SwapRoute[] = [ + // { + // tokenIn: tokens.mainnet.OETH, + // tokenOut: tokens.mainnet.WETH, + // action: 'swap-curve', + // }, + // { + // tokenIn: tokens.mainnet.OETH, + // tokenOut: tokens.mainnet.WETH, + // action: 'redeem-vault', + // }, { tokenIn: tokens.mainnet.OETH, tokenOut: tokens.mainnet.WETH, - action: 'swap-curve', + action: 'arm', + meta: { + icon: ARM, + waitTime: defineMessage({ defaultMessage: '~1 min' }), + comingSoon: true, + }, }, { tokenIn: tokens.mainnet.OETH, tokenOut: tokens.mainnet.WETH, - action: 'redeem-vault', + action: 'redeem-vault-async', + meta: { + icon: OETH, + waitTime: defineMessage({ defaultMessage: '~10 days' }), + }, }, ]; diff --git a/libs/defi/oeth/src/redeem/hooks.ts b/libs/defi/oeth/src/redeem/hooks.ts new file mode 100644 index 000000000..c8f405f70 --- /dev/null +++ b/libs/defi/oeth/src/redeem/hooks.ts @@ -0,0 +1,22 @@ +import { useMemo } from 'react'; + +import { useSearchParams } from 'react-router-dom'; + +export const useViewSelect = () => { + const [search, setSearch] = useSearchParams({ + v: 'request', + }); + + return useMemo( + () => ({ + view: search.get('v') ?? 'request', + update: (newVal: 'request' | 'claim') => { + setSearch((params) => { + params.set('v', newVal); + return params; + }); + }, + }), + [search, setSearch], + ); +}; diff --git a/libs/defi/oeth/src/redeem/index.ts b/libs/defi/oeth/src/redeem/index.ts index a3820983e..2d32501e5 100644 --- a/libs/defi/oeth/src/redeem/index.ts +++ b/libs/defi/oeth/src/redeem/index.ts @@ -1 +1 @@ -export * from './routes'; +export * from './views/RedeemView'; diff --git a/libs/defi/oeth/src/redeem/routes.tsx b/libs/defi/oeth/src/redeem/routes.tsx deleted file mode 100644 index 6691d83d8..000000000 --- a/libs/defi/oeth/src/redeem/routes.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import { defineMessage } from 'react-intl'; - -import { ClaimView } from './views/ClaimView'; -import { RedeemView } from './views/RedeemView'; -import { RequestView } from './views/RequestView'; - -import type { NonIndexRouteObject } from 'react-router-dom'; - -export const oethRedeemRoute: NonIndexRouteObject = { - path: 'redeem', - Component: RedeemView, - children: [ - { - index: true, - Component: RequestView, - handle: { label: defineMessage({ defaultMessage: 'Request' }) }, - }, - { - path: 'claim', - Component: ClaimView, - handle: { label: defineMessage({ defaultMessage: 'Claim' }) }, - }, - ], -}; diff --git a/libs/defi/oeth/src/redeem/types.ts b/libs/defi/oeth/src/redeem/types.ts index a9ad46da7..3e40efc18 100644 --- a/libs/defi/oeth/src/redeem/types.ts +++ b/libs/defi/oeth/src/redeem/types.ts @@ -1 +1,15 @@ -export type OethRedeemAction = 'swap-curve' | 'redeem-vault'; +import type { SvgIconProps } from '@mui/material'; +import type { ComponentType } from 'react'; +import type { MessageDescriptor } from 'react-intl'; + +export type Meta = { + icon?: ComponentType; + waitTime?: MessageDescriptor; + comingSoon?: boolean; +}; + +export type OethRedeemAction = + | 'arm' + | 'redeem-vault' + | 'redeem-vault-async' + | 'swap-curve'; diff --git a/libs/defi/oeth/src/redeem/views/RedeemView.tsx b/libs/defi/oeth/src/redeem/views/RedeemView.tsx index c5cfa17d8..1b29756d6 100644 --- a/libs/defi/oeth/src/redeem/views/RedeemView.tsx +++ b/libs/defi/oeth/src/redeem/views/RedeemView.tsx @@ -1,12 +1,22 @@ -import { Page, PageSection, PageTitle } from '@origin/defi/shared'; +import { Stack } from '@mui/material'; +import { + Page, + PageSection, + PageTitle, + trackSentryError, +} from '@origin/defi/shared'; +import { ErrorBoundary, ErrorCard } from '@origin/shared/components'; import { tokens } from '@origin/shared/contracts'; import { useIntl } from 'react-intl'; -import { Outlet } from 'react-router-dom'; + +import { ViewSwitch } from '../components/ViewSwitch'; +import { useViewSelect } from '../hooks'; +import { ClaimView } from './ClaimView'; +import { RequestView } from './RequestView'; export const RedeemView = () => { const intl = useIntl(); - // const navigate = useNavigate(); - // const location = useLocation(); + const { view } = useViewSelect(); return ( @@ -17,30 +27,17 @@ export const RedeemView = () => { })} token={tokens.mainnet.OETH} /> - {/* { - navigate(value); - }} - sx={{ mb: 5 }} - > - {oethRedeemRoute?.children?.map((route) => { - const path = route.index - ? '/oeth/redeem' - : `/oeth/redeem/${route.path}`; - return ( - - ); - })} - */} - + + + } + onError={trackSentryError} + > + {view === 'request' ? : } + + ); diff --git a/libs/shared/contracts/abi-json/OETHVault.json b/libs/shared/contracts/abi-json/OETHVault.json index c3ca21d39..32dbce3c0 100644 --- a/libs/shared/contracts/abi-json/OETHVault.json +++ b/libs/shared/contracts/abi-json/OETHVault.json @@ -1 +1,1397 @@ -[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_threshold","type":"uint256"}],"name":"AllocateThresholdUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_asset","type":"address"},{"indexed":false,"internalType":"address","name":"_strategy","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"AssetAllocated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_asset","type":"address"},{"indexed":false,"internalType":"address","name":"_strategy","type":"address"}],"name":"AssetDefaultStrategyUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_asset","type":"address"}],"name":"AssetSupported","type":"event"},{"anonymous":false,"inputs":[],"name":"CapitalPaused","type":"event"},{"anonymous":false,"inputs":[],"name":"CapitalUnpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousGovernor","type":"address"},{"indexed":true,"internalType":"address","name":"newGovernor","type":"address"}],"name":"GovernorshipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"maxSupplyDiff","type":"uint256"}],"name":"MaxSupplyDiffChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_addr","type":"address"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_threshold","type":"uint256"}],"name":"NetOusdMintForStrategyThresholdChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_ousdMetaStrategy","type":"address"}],"name":"OusdMetaStrategyUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousGovernor","type":"address"},{"indexed":true,"internalType":"address","name":"newGovernor","type":"address"}],"name":"PendingGovernorshipTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_priceProvider","type":"address"}],"name":"PriceProviderUpdated","type":"event"},{"anonymous":false,"inputs":[],"name":"RebasePaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_threshold","type":"uint256"}],"name":"RebaseThresholdUpdated","type":"event"},{"anonymous":false,"inputs":[],"name":"RebaseUnpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_addr","type":"address"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"Redeem","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_redeemFeeBps","type":"uint256"}],"name":"RedeemFeeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_address","type":"address"}],"name":"StrategistUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_addr","type":"address"}],"name":"StrategyApproved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_addr","type":"address"}],"name":"StrategyRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_address","type":"address"}],"name":"TrusteeAddressChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_basis","type":"uint256"}],"name":"TrusteeFeeBpsChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_vaultBuffer","type":"uint256"}],"name":"VaultBufferUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"uint256","name":"_yield","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_fee","type":"uint256"}],"name":"YieldDistribution","type":"event"},{"inputs":[{"internalType":"address","name":"_addr","type":"address"}],"name":"approveStrategy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"assetDefaultStrategies","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"autoAllocateThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_asset","type":"address"}],"name":"cacheDecimals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"capitalPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimGovernance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_strategyToAddress","type":"address"},{"internalType":"address[]","name":"_assets","type":"address[]"},{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"}],"name":"depositToStrategy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"governor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_priceProvider","type":"address"},{"internalType":"address","name":"_ousd","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isGovernor","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSupplyDiff","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"netOusdMintForStrategyThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"netOusdMintedForStrategy","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ousdMetaStrategy","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pauseCapital","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pauseRebase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"priceProvider","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_strategyFromAddress","type":"address"},{"internalType":"address","name":"_strategyToAddress","type":"address"},{"internalType":"address[]","name":"_assets","type":"address[]"},{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"}],"name":"reallocate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rebasePaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rebaseThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"redeemFeeBps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_addr","type":"address"}],"name":"removeStrategy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImpl","type":"address"}],"name":"setAdminImpl","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_asset","type":"address"},{"internalType":"address","name":"_strategy","type":"address"}],"name":"setAssetDefaultStrategy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_threshold","type":"uint256"}],"name":"setAutoAllocateThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxSupplyDiff","type":"uint256"}],"name":"setMaxSupplyDiff","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_threshold","type":"uint256"}],"name":"setNetOusdMintForStrategyThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_ousdMetaStrategy","type":"address"}],"name":"setOusdMetaStrategy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_priceProvider","type":"address"}],"name":"setPriceProvider","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_threshold","type":"uint256"}],"name":"setRebaseThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_redeemFeeBps","type":"uint256"}],"name":"setRedeemFeeBps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"setStrategistAddr","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"setTrusteeAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_basis","type":"uint256"}],"name":"setTrusteeFeeBps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vaultBuffer","type":"uint256"}],"name":"setVaultBuffer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"strategistAddr","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_asset","type":"address"},{"internalType":"uint8","name":"_unitConversion","type":"uint8"}],"name":"supportAsset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newGovernor","type":"address"}],"name":"transferGovernance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_asset","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"transferToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"trusteeAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"trusteeFeeBps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpauseCapital","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpauseRebase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"vaultBuffer","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawAllFromStrategies","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_strategyAddr","type":"address"}],"name":"withdrawAllFromStrategy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_strategyFromAddress","type":"address"},{"internalType":"address[]","name":"_assets","type":"address[]"},{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"}],"name":"withdrawFromStrategy","outputs":[],"stateMutability":"nonpayable","type":"function"}] +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_threshold", + "type": "uint256" + } + ], + "name": "AllocateThresholdUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "_strategy", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "AssetAllocated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "_strategy", + "type": "address" + } + ], + "name": "AssetDefaultStrategyUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_asset", + "type": "address" + } + ], + "name": "AssetSupported", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "CapitalPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "CapitalUnpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "maxSupplyDiff", + "type": "uint256" + } + ], + "name": "MaxSupplyDiffChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_addr", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_priceProvider", + "type": "address" + } + ], + "name": "PriceProviderUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "RebasePaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_threshold", + "type": "uint256" + } + ], + "name": "RebaseThresholdUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "RebaseUnpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_addr", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_redeemFeeBps", + "type": "uint256" + } + ], + "name": "RedeemFeeUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_address", + "type": "address" + } + ], + "name": "StrategistUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_addr", + "type": "address" + } + ], + "name": "StrategyApproved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_addr", + "type": "address" + } + ], + "name": "StrategyRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_basis", + "type": "uint256" + } + ], + "name": "SwapAllowedUndervalueChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_basis", + "type": "uint256" + } + ], + "name": "SwapSlippageChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "_fromAsset", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "_toAsset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_fromAssetAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_toAssetAmount", + "type": "uint256" + } + ], + "name": "Swapped", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_address", + "type": "address" + } + ], + "name": "SwapperChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_address", + "type": "address" + } + ], + "name": "TrusteeAddressChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_basis", + "type": "uint256" + } + ], + "name": "TrusteeFeeBpsChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_vaultBuffer", + "type": "uint256" + } + ], + "name": "VaultBufferUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_yield", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_fee", + "type": "uint256" + } + ], + "name": "YieldDistribution", + "type": "event" + }, + { + "inputs": [], + "name": "allocate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "allowedSwapUndervalue", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_addr", + "type": "address" + } + ], + "name": "approveStrategy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_asset", + "type": "address" + } + ], + "name": "assetDefaultStrategies", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "autoAllocateThreshold", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "burnForStrategy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "cacheWETHAssetIndex", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "calculateRedeemOutputs", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "capitalPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_asset", + "type": "address" + } + ], + "name": "checkBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "claimGovernance", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_strategyToAddress", + "type": "address" + }, + { + "internalType": "address[]", + "name": "_assets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "_amounts", + "type": "uint256[]" + } + ], + "name": "depositToStrategy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getAllAssets", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAllStrategies", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_asset", + "type": "address" + } + ], + "name": "getAssetConfig", + "outputs": [ + { + "components": [ + { + "internalType": "bool", + "name": "isSupported", + "type": "bool" + }, + { + "internalType": "enum VaultStorage.UnitConversion", + "name": "unitConversion", + "type": "uint8" + }, + { + "internalType": "uint8", + "name": "decimals", + "type": "uint8" + }, + { + "internalType": "uint16", + "name": "allowedOracleSlippageBps", + "type": "uint16" + } + ], + "internalType": "struct VaultStorage.Asset", + "name": "config", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAssetCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getStrategyCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "governor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_asset", + "type": "address" + } + ], + "name": "isSupportedAsset", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxSupplyDiff", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_minimumOusdAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "mintForStrategy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "netOusdMintForStrategyThreshold", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "netOusdMintedForStrategy", + "outputs": [ + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ousdMetaStrategy", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pauseCapital", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pauseRebase", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "priceProvider", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "priceUnitMint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "priceUnitRedeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rebase", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "rebasePaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rebaseThreshold", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_minimumUnitAmount", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_minimumUnitAmount", + "type": "uint256" + } + ], + "name": "redeemAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "redeemFeeBps", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_asset", + "type": "address" + } + ], + "name": "removeAsset", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_addr", + "type": "address" + } + ], + "name": "removeStrategy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "setAdminImpl", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_asset", + "type": "address" + }, + { + "internalType": "address", + "name": "_strategy", + "type": "address" + } + ], + "name": "setAssetDefaultStrategy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_threshold", + "type": "uint256" + } + ], + "name": "setAutoAllocateThreshold", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_maxSupplyDiff", + "type": "uint256" + } + ], + "name": "setMaxSupplyDiff", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_threshold", + "type": "uint256" + } + ], + "name": "setNetOusdMintForStrategyThreshold", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_asset", + "type": "address" + }, + { + "internalType": "uint16", + "name": "_allowedOracleSlippageBps", + "type": "uint16" + } + ], + "name": "setOracleSlippage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_ousdMetaStrategy", + "type": "address" + } + ], + "name": "setOusdMetaStrategy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_priceProvider", + "type": "address" + } + ], + "name": "setPriceProvider", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_threshold", + "type": "uint256" + } + ], + "name": "setRebaseThreshold", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_redeemFeeBps", + "type": "uint256" + } + ], + "name": "setRedeemFeeBps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_address", + "type": "address" + } + ], + "name": "setStrategistAddr", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "_percentageBps", + "type": "uint16" + } + ], + "name": "setSwapAllowedUndervalue", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_swapperAddr", + "type": "address" + } + ], + "name": "setSwapper", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_address", + "type": "address" + } + ], + "name": "setTrusteeAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_basis", + "type": "uint256" + } + ], + "name": "setTrusteeFeeBps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_vaultBuffer", + "type": "uint256" + } + ], + "name": "setVaultBuffer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "strategistAddr", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_asset", + "type": "address" + }, + { + "internalType": "uint8", + "name": "_supportsAsset", + "type": "uint8" + } + ], + "name": "supportAsset", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "fromAsset", + "type": "address" + }, + { + "internalType": "address", + "name": "toAsset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "fromAssetAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minToAssetAmount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "swapCollateral", + "outputs": [ + { + "internalType": "uint256", + "name": "toAssetAmount", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "swapper", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalValue", + "outputs": [ + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newGovernor", + "type": "address" + } + ], + "name": "transferGovernance", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "transferToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "trusteeAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "trusteeFeeBps", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "unpauseCapital", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpauseRebase", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "vaultBuffer", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "weth", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "wethAssetIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawAllFromStrategies", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_strategyAddr", + "type": "address" + } + ], + "name": "withdrawAllFromStrategy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_strategyFromAddress", + "type": "address" + }, + { + "internalType": "address[]", + "name": "_assets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "_amounts", + "type": "uint256[]" + } + ], + "name": "withdrawFromStrategy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/libs/shared/contracts/src/abis/OETHVault.ts b/libs/shared/contracts/src/abis/OETHVault.ts index eded276d8..bf576b535 100644 --- a/libs/shared/contracts/src/abis/OETHVault.ts +++ b/libs/shared/contracts/src/abis/OETHVault.ts @@ -1,4 +1,3 @@ -// DO NOT EDIT - GENERATED export const OETHVaultABI = [ { anonymous: false, @@ -70,25 +69,29 @@ export const OETHVaultABI = [ name: 'AssetSupported', type: 'event', }, - { anonymous: false, inputs: [], name: 'CapitalPaused', type: 'event' }, - { anonymous: false, inputs: [], name: 'CapitalUnpaused', type: 'event' }, + { + anonymous: false, + inputs: [], + name: 'CapitalPaused', + type: 'event', + }, + { + anonymous: false, + inputs: [], + name: 'CapitalUnpaused', + type: 'event', + }, { anonymous: false, inputs: [ { indexed: true, internalType: 'address', - name: 'previousGovernor', - type: 'address', - }, - { - indexed: true, - internalType: 'address', - name: 'newGovernor', + name: '_dripper', type: 'address', }, ], - name: 'GovernorshipTransferred', + name: 'DripperChanged', type: 'event', }, { @@ -123,6 +126,25 @@ export const OETHVaultABI = [ name: 'Mint', type: 'event', }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: 'address', + name: '_priceProvider', + type: 'address', + }, + ], + name: 'PriceProviderUpdated', + type: 'event', + }, + { + anonymous: false, + inputs: [], + name: 'RebasePaused', + type: 'event', + }, { anonymous: false, inputs: [ @@ -133,7 +155,13 @@ export const OETHVaultABI = [ type: 'uint256', }, ], - name: 'NetOusdMintForStrategyThresholdChanged', + name: 'RebaseThresholdUpdated', + type: 'event', + }, + { + anonymous: false, + inputs: [], + name: 'RebaseUnpaused', type: 'event', }, { @@ -142,30 +170,56 @@ export const OETHVaultABI = [ { indexed: false, internalType: 'address', - name: '_ousdMetaStrategy', + name: '_addr', type: 'address', }, + { + indexed: false, + internalType: 'uint256', + name: '_value', + type: 'uint256', + }, + ], + name: 'Redeem', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: 'uint256', + name: '_redeemFeeBps', + type: 'uint256', + }, ], - name: 'OusdMetaStrategyUpdated', + name: 'RedeemFeeUpdated', type: 'event', }, { anonymous: false, inputs: [ { - indexed: true, + indexed: false, internalType: 'address', - name: 'previousGovernor', + name: '_address', type: 'address', }, + ], + name: 'StrategistUpdated', + type: 'event', + }, + { + anonymous: false, + inputs: [ { - indexed: true, + indexed: false, internalType: 'address', - name: 'newGovernor', + name: '_addr', type: 'address', }, ], - name: 'PendingGovernorshipTransfer', + name: 'StrategyApproved', type: 'event', }, { @@ -174,58 +228,74 @@ export const OETHVaultABI = [ { indexed: false, internalType: 'address', - name: '_priceProvider', + name: '_addr', type: 'address', }, ], - name: 'PriceProviderUpdated', + name: 'StrategyRemoved', type: 'event', }, - { anonymous: false, inputs: [], name: 'RebasePaused', type: 'event' }, { anonymous: false, inputs: [ { indexed: false, internalType: 'uint256', - name: '_threshold', + name: '_basis', type: 'uint256', }, ], - name: 'RebaseThresholdUpdated', + name: 'SwapAllowedUndervalueChanged', type: 'event', }, - { anonymous: false, inputs: [], name: 'RebaseUnpaused', type: 'event' }, { anonymous: false, inputs: [ { indexed: false, internalType: 'address', - name: '_addr', + name: '_asset', type: 'address', }, { indexed: false, internalType: 'uint256', - name: '_value', + name: '_basis', type: 'uint256', }, ], - name: 'Redeem', + name: 'SwapSlippageChanged', type: 'event', }, { anonymous: false, inputs: [ + { + indexed: true, + internalType: 'address', + name: '_fromAsset', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: '_toAsset', + type: 'address', + }, { indexed: false, internalType: 'uint256', - name: '_redeemFeeBps', + name: '_fromAssetAmount', + type: 'uint256', + }, + { + indexed: false, + internalType: 'uint256', + name: '_toAssetAmount', type: 'uint256', }, ], - name: 'RedeemFeeUpdated', + name: 'Swapped', type: 'event', }, { @@ -238,7 +308,7 @@ export const OETHVaultABI = [ type: 'address', }, ], - name: 'StrategistUpdated', + name: 'SwapperChanged', type: 'event', }, { @@ -247,11 +317,11 @@ export const OETHVaultABI = [ { indexed: false, internalType: 'address', - name: '_addr', + name: '_address', type: 'address', }, ], - name: 'StrategyApproved', + name: 'TrusteeAddressChanged', type: 'event', }, { @@ -259,12 +329,12 @@ export const OETHVaultABI = [ inputs: [ { indexed: false, - internalType: 'address', - name: '_addr', - type: 'address', + internalType: 'uint256', + name: '_basis', + type: 'uint256', }, ], - name: 'StrategyRemoved', + name: 'TrusteeFeeBpsChanged', type: 'event', }, { @@ -272,12 +342,12 @@ export const OETHVaultABI = [ inputs: [ { indexed: false, - internalType: 'address', - name: '_address', - type: 'address', + internalType: 'uint256', + name: '_vaultBuffer', + type: 'uint256', }, ], - name: 'TrusteeAddressChanged', + name: 'VaultBufferUpdated', type: 'event', }, { @@ -286,30 +356,84 @@ export const OETHVaultABI = [ { indexed: false, internalType: 'uint256', - name: '_basis', + name: '_claimable', + type: 'uint256', + }, + { + indexed: false, + internalType: 'uint256', + name: '_newClaimable', type: 'uint256', }, ], - name: 'TrusteeFeeBpsChanged', + name: 'WithdrawalClaimable', type: 'event', }, { anonymous: false, inputs: [ + { + indexed: true, + internalType: 'address', + name: '_withdrawer', + type: 'address', + }, + { + indexed: true, + internalType: 'uint256', + name: '_requestId', + type: 'uint256', + }, { indexed: false, internalType: 'uint256', - name: '_vaultBuffer', + name: '_amount', type: 'uint256', }, ], - name: 'VaultBufferUpdated', + name: 'WithdrawalClaimed', + type: 'event', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'address', + name: '_withdrawer', + type: 'address', + }, + { + indexed: true, + internalType: 'uint256', + name: '_requestId', + type: 'uint256', + }, + { + indexed: false, + internalType: 'uint256', + name: '_amount', + type: 'uint256', + }, + { + indexed: false, + internalType: 'uint256', + name: '_queued', + type: 'uint256', + }, + ], + name: 'WithdrawalRequested', type: 'event', }, { anonymous: false, inputs: [ - { indexed: false, internalType: 'address', name: '_to', type: 'address' }, + { + indexed: false, + internalType: 'address', + name: '_to', + type: 'address', + }, { indexed: false, internalType: 'uint256', @@ -327,107 +451,449 @@ export const OETHVaultABI = [ type: 'event', }, { - inputs: [{ internalType: 'address', name: '_addr', type: 'address' }], - name: 'approveStrategy', + inputs: [], + name: 'addWithdrawalQueueLiquidity', outputs: [], stateMutability: 'nonpayable', type: 'function', }, - { - inputs: [{ internalType: 'address', name: '', type: 'address' }], - name: 'assetDefaultStrategies', - outputs: [{ internalType: 'address', name: '', type: 'address' }], - stateMutability: 'view', - type: 'function', - }, { inputs: [], - name: 'autoAllocateThreshold', - outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], - stateMutability: 'view', - type: 'function', - }, - { - inputs: [{ internalType: 'address', name: '_asset', type: 'address' }], - name: 'cacheDecimals', + name: 'allocate', outputs: [], stateMutability: 'nonpayable', type: 'function', }, { inputs: [], - name: 'capitalPaused', - outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + name: 'allowedSwapUndervalue', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], stateMutability: 'view', type: 'function', }, { - inputs: [], - name: 'claimGovernance', + inputs: [ + { + internalType: 'address', + name: '_addr', + type: 'address', + }, + ], + name: 'approveStrategy', outputs: [], stateMutability: 'nonpayable', type: 'function', }, { inputs: [ - { internalType: 'address', name: '_strategyToAddress', type: 'address' }, - { internalType: 'address[]', name: '_assets', type: 'address[]' }, - { internalType: 'uint256[]', name: '_amounts', type: 'uint256[]' }, + { + internalType: 'address', + name: '_asset', + type: 'address', + }, ], - name: 'depositToStrategy', - outputs: [], - stateMutability: 'nonpayable', + name: 'assetDefaultStrategies', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', type: 'function', }, { inputs: [], - name: 'governor', - outputs: [{ internalType: 'address', name: '', type: 'address' }], + name: 'autoAllocateThreshold', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], stateMutability: 'view', type: 'function', }, { inputs: [ - { internalType: 'address', name: '_priceProvider', type: 'address' }, - { internalType: 'address', name: '_ousd', type: 'address' }, + { + internalType: 'uint256', + name: '_amount', + type: 'uint256', + }, ], - name: 'initialize', + name: 'burnForStrategy', outputs: [], stateMutability: 'nonpayable', type: 'function', }, { inputs: [], - name: 'isGovernor', - outputs: [{ internalType: 'bool', name: '', type: 'bool' }], - stateMutability: 'view', + name: 'cacheWETHAssetIndex', + outputs: [], + stateMutability: 'nonpayable', type: 'function', }, { - inputs: [], - name: 'maxSupplyDiff', - outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + inputs: [ + { + internalType: 'uint256', + name: '_amount', + type: 'uint256', + }, + ], + name: 'calculateRedeemOutputs', + outputs: [ + { + internalType: 'uint256[]', + name: '', + type: 'uint256[]', + }, + ], stateMutability: 'view', type: 'function', }, { inputs: [], - name: 'netOusdMintForStrategyThreshold', - outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + name: 'capitalPaused', + outputs: [ + { + internalType: 'bool', + name: '', + type: 'bool', + }, + ], stateMutability: 'view', type: 'function', }, { - inputs: [], - name: 'netOusdMintedForStrategy', - outputs: [{ internalType: 'int256', name: '', type: 'int256' }], - stateMutability: 'view', + inputs: [ + { + internalType: 'address', + name: '_asset', + type: 'address', + }, + ], + name: 'checkBalance', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'claimGovernance', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'uint256', + name: 'requestId', + type: 'uint256', + }, + ], + name: 'claimWithdrawal', + outputs: [ + { + internalType: 'uint256', + name: 'amount', + type: 'uint256', + }, + ], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'uint256[]', + name: 'requestIds', + type: 'uint256[]', + }, + ], + name: 'claimWithdrawals', + outputs: [ + { + internalType: 'uint256[]', + name: 'amounts', + type: 'uint256[]', + }, + { + internalType: 'uint256', + name: 'totalAmount', + type: 'uint256', + }, + ], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: '_strategyToAddress', + type: 'address', + }, + { + internalType: 'address[]', + name: '_assets', + type: 'address[]', + }, + { + internalType: 'uint256[]', + name: '_amounts', + type: 'uint256[]', + }, + ], + name: 'depositToStrategy', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'getAllAssets', + outputs: [ + { + internalType: 'address[]', + name: '', + type: 'address[]', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'getAllStrategies', + outputs: [ + { + internalType: 'address[]', + name: '', + type: 'address[]', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: '_asset', + type: 'address', + }, + ], + name: 'getAssetConfig', + outputs: [ + { + components: [ + { + internalType: 'bool', + name: 'isSupported', + type: 'bool', + }, + { + internalType: 'enum VaultStorage.UnitConversion', + name: 'unitConversion', + type: 'uint8', + }, + { + internalType: 'uint8', + name: 'decimals', + type: 'uint8', + }, + { + internalType: 'uint16', + name: 'allowedOracleSlippageBps', + type: 'uint16', + }, + ], + internalType: 'struct VaultStorage.Asset', + name: 'config', + type: 'tuple', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'getAssetCount', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'getStrategyCount', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'governor', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + name: 'initialize', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: '_asset', + type: 'address', + }, + ], + name: 'isSupportedAsset', + outputs: [ + { + internalType: 'bool', + name: '', + type: 'bool', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'maxSupplyDiff', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: '_asset', + type: 'address', + }, + { + internalType: 'uint256', + name: '_amount', + type: 'uint256', + }, + { + internalType: 'uint256', + name: '_minimumOusdAmount', + type: 'uint256', + }, + ], + name: 'mint', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'uint256', + name: '_amount', + type: 'uint256', + }, + ], + name: 'mintForStrategy', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'netOusdMintForStrategyThreshold', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'netOusdMintedForStrategy', + outputs: [ + { + internalType: 'int256', + name: '', + type: 'int256', + }, + ], + stateMutability: 'view', type: 'function', }, { inputs: [], name: 'ousdMetaStrategy', - outputs: [{ internalType: 'address', name: '', type: 'address' }], + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], stateMutability: 'view', type: 'function', }, @@ -448,7 +914,13 @@ export const OETHVaultABI = [ { inputs: [], name: 'priceProvider', - outputs: [{ internalType: 'address', name: '', type: 'address' }], + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], stateMutability: 'view', type: 'function', }, @@ -456,14 +928,43 @@ export const OETHVaultABI = [ inputs: [ { internalType: 'address', - name: '_strategyFromAddress', + name: 'asset', + type: 'address', + }, + ], + name: 'priceUnitMint', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: 'asset', type: 'address', }, - { internalType: 'address', name: '_strategyToAddress', type: 'address' }, - { internalType: 'address[]', name: '_assets', type: 'address[]' }, - { internalType: 'uint256[]', name: '_amounts', type: 'uint256[]' }, ], - name: 'reallocate', + name: 'priceUnitRedeem', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'rebase', outputs: [], stateMutability: 'nonpayable', type: 'function', @@ -471,121 +972,336 @@ export const OETHVaultABI = [ { inputs: [], name: 'rebasePaused', - outputs: [{ internalType: 'bool', name: '', type: 'bool' }], + outputs: [ + { + internalType: 'bool', + name: '', + type: 'bool', + }, + ], stateMutability: 'view', type: 'function', }, { inputs: [], name: 'rebaseThreshold', - outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], stateMutability: 'view', type: 'function', }, { - inputs: [], - name: 'redeemFeeBps', - outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], - stateMutability: 'view', + inputs: [ + { + internalType: 'uint256', + name: '_amount', + type: 'uint256', + }, + { + internalType: 'uint256', + name: '_minimumUnitAmount', + type: 'uint256', + }, + ], + name: 'redeem', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'uint256', + name: '_minimumUnitAmount', + type: 'uint256', + }, + ], + name: 'redeemAll', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'redeemFeeBps', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: '_asset', + type: 'address', + }, + ], + name: 'removeAsset', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: '_addr', + type: 'address', + }, + ], + name: 'removeStrategy', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'uint256', + name: '_amount', + type: 'uint256', + }, + ], + name: 'requestWithdrawal', + outputs: [ + { + internalType: 'uint256', + name: 'requestId', + type: 'uint256', + }, + { + internalType: 'uint256', + name: 'queued', + type: 'uint256', + }, + ], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + name: 'setAdminImpl', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: '_asset', + type: 'address', + }, + { + internalType: 'address', + name: '_strategy', + type: 'address', + }, + ], + name: 'setAssetDefaultStrategy', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [ + { + internalType: 'uint256', + name: '_threshold', + type: 'uint256', + }, + ], + name: 'setAutoAllocateThreshold', + outputs: [], + stateMutability: 'nonpayable', type: 'function', }, { - inputs: [{ internalType: 'address', name: '_addr', type: 'address' }], - name: 'removeStrategy', + inputs: [ + { + internalType: 'address', + name: '_dripper', + type: 'address', + }, + ], + name: 'setDripper', outputs: [], stateMutability: 'nonpayable', type: 'function', }, { - inputs: [{ internalType: 'address', name: 'newImpl', type: 'address' }], - name: 'setAdminImpl', + inputs: [ + { + internalType: 'uint256', + name: '_maxSupplyDiff', + type: 'uint256', + }, + ], + name: 'setMaxSupplyDiff', outputs: [], stateMutability: 'nonpayable', type: 'function', }, { inputs: [ - { internalType: 'address', name: '_asset', type: 'address' }, - { internalType: 'address', name: '_strategy', type: 'address' }, + { + internalType: 'uint256', + name: '_threshold', + type: 'uint256', + }, ], - name: 'setAssetDefaultStrategy', + name: 'setNetOusdMintForStrategyThreshold', outputs: [], stateMutability: 'nonpayable', type: 'function', }, { - inputs: [{ internalType: 'uint256', name: '_threshold', type: 'uint256' }], - name: 'setAutoAllocateThreshold', + inputs: [ + { + internalType: 'address', + name: '_asset', + type: 'address', + }, + { + internalType: 'uint16', + name: '_allowedOracleSlippageBps', + type: 'uint16', + }, + ], + name: 'setOracleSlippage', outputs: [], stateMutability: 'nonpayable', type: 'function', }, { inputs: [ - { internalType: 'uint256', name: '_maxSupplyDiff', type: 'uint256' }, + { + internalType: 'address', + name: '_ousdMetaStrategy', + type: 'address', + }, ], - name: 'setMaxSupplyDiff', + name: 'setOusdMetaStrategy', outputs: [], stateMutability: 'nonpayable', type: 'function', }, { - inputs: [{ internalType: 'uint256', name: '_threshold', type: 'uint256' }], - name: 'setNetOusdMintForStrategyThreshold', + inputs: [ + { + internalType: 'address', + name: '_priceProvider', + type: 'address', + }, + ], + name: 'setPriceProvider', outputs: [], stateMutability: 'nonpayable', type: 'function', }, { inputs: [ - { internalType: 'address', name: '_ousdMetaStrategy', type: 'address' }, + { + internalType: 'uint256', + name: '_threshold', + type: 'uint256', + }, ], - name: 'setOusdMetaStrategy', + name: 'setRebaseThreshold', outputs: [], stateMutability: 'nonpayable', type: 'function', }, { inputs: [ - { internalType: 'address', name: '_priceProvider', type: 'address' }, + { + internalType: 'uint256', + name: '_redeemFeeBps', + type: 'uint256', + }, ], - name: 'setPriceProvider', + name: 'setRedeemFeeBps', outputs: [], stateMutability: 'nonpayable', type: 'function', }, { - inputs: [{ internalType: 'uint256', name: '_threshold', type: 'uint256' }], - name: 'setRebaseThreshold', + inputs: [ + { + internalType: 'address', + name: '_address', + type: 'address', + }, + ], + name: 'setStrategistAddr', outputs: [], stateMutability: 'nonpayable', type: 'function', }, { inputs: [ - { internalType: 'uint256', name: '_redeemFeeBps', type: 'uint256' }, + { + internalType: 'uint16', + name: '_percentageBps', + type: 'uint16', + }, ], - name: 'setRedeemFeeBps', + name: 'setSwapAllowedUndervalue', outputs: [], stateMutability: 'nonpayable', type: 'function', }, { - inputs: [{ internalType: 'address', name: '_address', type: 'address' }], - name: 'setStrategistAddr', + inputs: [ + { + internalType: 'address', + name: '_swapperAddr', + type: 'address', + }, + ], + name: 'setSwapper', outputs: [], stateMutability: 'nonpayable', type: 'function', }, { - inputs: [{ internalType: 'address', name: '_address', type: 'address' }], + inputs: [ + { + internalType: 'address', + name: '_address', + type: 'address', + }, + ], name: 'setTrusteeAddress', outputs: [], stateMutability: 'nonpayable', type: 'function', }, { - inputs: [{ internalType: 'uint256', name: '_basis', type: 'uint256' }], + inputs: [ + { + internalType: 'uint256', + name: '_basis', + type: 'uint256', + }, + ], name: 'setTrusteeFeeBps', outputs: [], stateMutability: 'nonpayable', @@ -593,7 +1309,11 @@ export const OETHVaultABI = [ }, { inputs: [ - { internalType: 'uint256', name: '_vaultBuffer', type: 'uint256' }, + { + internalType: 'uint256', + name: '_vaultBuffer', + type: 'uint256', + }, ], name: 'setVaultBuffer', outputs: [], @@ -603,14 +1323,28 @@ export const OETHVaultABI = [ { inputs: [], name: 'strategistAddr', - outputs: [{ internalType: 'address', name: '', type: 'address' }], + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], stateMutability: 'view', type: 'function', }, { inputs: [ - { internalType: 'address', name: '_asset', type: 'address' }, - { internalType: 'uint8', name: '_unitConversion', type: 'uint8' }, + { + internalType: 'address', + name: '_asset', + type: 'address', + }, + { + internalType: 'uint8', + name: '_supportsAsset', + type: 'uint8', + }, ], name: 'supportAsset', outputs: [], @@ -619,7 +1353,76 @@ export const OETHVaultABI = [ }, { inputs: [ - { internalType: 'address', name: '_newGovernor', type: 'address' }, + { + internalType: 'address', + name: 'fromAsset', + type: 'address', + }, + { + internalType: 'address', + name: 'toAsset', + type: 'address', + }, + { + internalType: 'uint256', + name: 'fromAssetAmount', + type: 'uint256', + }, + { + internalType: 'uint256', + name: 'minToAssetAmount', + type: 'uint256', + }, + { + internalType: 'bytes', + name: 'data', + type: 'bytes', + }, + ], + name: 'swapCollateral', + outputs: [ + { + internalType: 'uint256', + name: 'toAssetAmount', + type: 'uint256', + }, + ], + stateMutability: 'nonpayable', + type: 'function', + }, + { + inputs: [], + name: 'swapper', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'totalValue', + outputs: [ + { + internalType: 'uint256', + name: 'value', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'address', + name: '_newGovernor', + type: 'address', + }, ], name: 'transferGovernance', outputs: [], @@ -628,8 +1431,16 @@ export const OETHVaultABI = [ }, { inputs: [ - { internalType: 'address', name: '_asset', type: 'address' }, - { internalType: 'uint256', name: '_amount', type: 'uint256' }, + { + internalType: 'address', + name: '_asset', + type: 'address', + }, + { + internalType: 'uint256', + name: '_amount', + type: 'uint256', + }, ], name: 'transferToken', outputs: [], @@ -639,14 +1450,26 @@ export const OETHVaultABI = [ { inputs: [], name: 'trusteeAddress', - outputs: [{ internalType: 'address', name: '', type: 'address' }], + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], stateMutability: 'view', type: 'function', }, { inputs: [], name: 'trusteeFeeBps', - outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], stateMutability: 'view', type: 'function', }, @@ -667,7 +1490,39 @@ export const OETHVaultABI = [ { inputs: [], name: 'vaultBuffer', - outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }], + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'weth', + outputs: [ + { + internalType: 'address', + name: '', + type: 'address', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [], + name: 'wethAssetIndex', + outputs: [ + { + internalType: 'uint256', + name: '', + type: 'uint256', + }, + ], stateMutability: 'view', type: 'function', }, @@ -680,7 +1535,11 @@ export const OETHVaultABI = [ }, { inputs: [ - { internalType: 'address', name: '_strategyAddr', type: 'address' }, + { + internalType: 'address', + name: '_strategyAddr', + type: 'address', + }, ], name: 'withdrawAllFromStrategy', outputs: [], @@ -694,12 +1553,96 @@ export const OETHVaultABI = [ name: '_strategyFromAddress', type: 'address', }, - { internalType: 'address[]', name: '_assets', type: 'address[]' }, - { internalType: 'uint256[]', name: '_amounts', type: 'uint256[]' }, + { + internalType: 'address[]', + name: '_assets', + type: 'address[]', + }, + { + internalType: 'uint256[]', + name: '_amounts', + type: 'uint256[]', + }, ], name: 'withdrawFromStrategy', outputs: [], stateMutability: 'nonpayable', type: 'function', }, + { + inputs: [], + name: 'withdrawalQueueMetadata', + outputs: [ + { + components: [ + { + internalType: 'uint128', + name: 'queued', + type: 'uint128', + }, + { + internalType: 'uint128', + name: 'claimable', + type: 'uint128', + }, + { + internalType: 'uint128', + name: 'claimed', + type: 'uint128', + }, + { + internalType: 'uint128', + name: 'nextWithdrawalIndex', + type: 'uint128', + }, + ], + internalType: 'struct VaultStorage.WithdrawalQueueMetadata', + name: '', + type: 'tuple', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + inputs: [ + { + internalType: 'uint256', + name: 'requestId', + type: 'uint256', + }, + ], + name: 'withdrawalRequests', + outputs: [ + { + components: [ + { + internalType: 'address', + name: 'withdrawer', + type: 'address', + }, + { + internalType: 'bool', + name: 'claimed', + type: 'bool', + }, + { + internalType: 'uint128', + name: 'amount', + type: 'uint128', + }, + { + internalType: 'uint128', + name: 'queued', + type: 'uint128', + }, + ], + internalType: 'struct VaultStorage.WithdrawalRequest', + name: '', + type: 'tuple', + }, + ], + stateMutability: 'view', + type: 'function', + }, ] as const; diff --git a/libs/shared/contracts/src/contracts.ts b/libs/shared/contracts/src/contracts.ts index 2f9831646..52dcc752b 100644 --- a/libs/shared/contracts/src/contracts.ts +++ b/libs/shared/contracts/src/contracts.ts @@ -16,6 +16,7 @@ import { LrtDepositPoolABI } from './abis/LrtDepositPool'; import { LrtOracleABI } from './abis/LrtOracle'; import { MigratorABI } from './abis/Migrator'; import { OETHDripperABI } from './abis/OETHDripper'; +import { OETHVaultABI } from './abis/OETHVault'; import { OETHZapperABI } from './abis/OETHZapper'; import { OGNFixedRateRewardSourceABI } from './abis/OGNFixedRateRewardSource'; import { OGVMandatoryDistibutorABI } from './abis/OGVMandatoryDistibutor'; @@ -113,7 +114,7 @@ export const contracts = { OETHVault: { address: '0x39254033945AA2E4809Cc2977E7087BEE48bd7Ab', chainId: mainnet.id, - abi: IVaultABI, + abi: OETHVaultABI, name: 'OETHVault', }, OETHZapper: { diff --git a/libs/shared/icons/src/protocols/arm.svg b/libs/shared/icons/src/protocols/arm.svg new file mode 100644 index 000000000..e3c4957f4 --- /dev/null +++ b/libs/shared/icons/src/protocols/arm.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + diff --git a/libs/shared/icons/src/protocols/index.tsx b/libs/shared/icons/src/protocols/index.tsx index ba18fd2f8..ad9a1bf38 100644 --- a/libs/shared/icons/src/protocols/index.tsx +++ b/libs/shared/icons/src/protocols/index.tsx @@ -1,6 +1,7 @@ import { SvgIcon } from '@mui/material'; import AaveFullSvg from './aave-full.svg?react'; +import ArmSvg from './arm.svg?react'; import AuraFullWebp from './aura-full.webp'; import BalancerFullSvg from './balancer-full.svg?react'; import ChainlinkCCIPSvg from './chainlink-ccip.svg?react'; @@ -24,6 +25,9 @@ import type { SvgIconProps } from '@mui/material'; export const AaveFull = (props: SvgIconProps) => ( ); +export const ARM = (props: SvgIconProps) => ( + +); export const AuraFull = (props: SvgIconProps) => ( From f150a61c680228616c9e615be9590965d6fb17dd Mon Sep 17 00:00:00 2001 From: toniocodo Date: Tue, 9 Jul 2024 23:21:44 +0200 Subject: [PATCH 02/33] feat: split sign update, use callback before reset --- libs/shared/providers/src/swapper/hooks.ts | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/libs/shared/providers/src/swapper/hooks.ts b/libs/shared/providers/src/swapper/hooks.ts index 4f0e88db8..43dda6f6d 100644 --- a/libs/shared/providers/src/swapper/hooks.ts +++ b/libs/shared/providers/src/swapper/hooks.ts @@ -658,17 +658,12 @@ export const useHandleSwap = () => { status: 'swapWaitingForTransaction', })); if (hash) { - const txReceipt = await waitForTransactionReceipt(config, { hash }); - queryClient.invalidateQueries(); setSwapState((state) => ({ ...state, isSwapLoading: false, - amountIn: 0n, - amountOut: 0n, - estimatedSwapRoutes: [], - selectedSwapRoute: null, status: 'swapTransactionSuccess', })); + const txReceipt = await waitForTransactionReceipt(config, { hash }); onSwapSuccess?.({ ...state, txReceipt: txReceipt as unknown as TransactionReceipt, @@ -682,6 +677,14 @@ export const useHandleSwap = () => { swap_to: tokenOut.symbol, swap_amount: amountIn, }); + queryClient.invalidateQueries(); + setSwapState((state) => ({ + ...state, + amountIn: 0n, + amountOut: 0n, + estimatedSwapRoutes: [], + selectedSwapRoute: null, + })); } } catch (error) { setSwapState((state) => ({ From a4618cb7d02fd60360fdc64942b403fc9d58c3ad Mon Sep 17 00:00:00 2001 From: toniocodo Date: Tue, 9 Jul 2024 23:22:41 +0200 Subject: [PATCH 03/33] feat: add withdrawal request modal --- apps/defi/src/lang/en.json | 108 ++++++++++++---- apps/defi/src/lang/extracts/en.json | 42 +++++-- .../oeth/src/redeem/components/Swapper.tsx | 44 ++++++- .../components/WithdrawalRequestModal.tsx | 117 ++++++++++++++++++ 4 files changed, 271 insertions(+), 40 deletions(-) create mode 100644 libs/defi/oeth/src/redeem/components/WithdrawalRequestModal.tsx diff --git a/apps/defi/src/lang/en.json b/apps/defi/src/lang/en.json index f506d4cc3..50c3b3c28 100644 --- a/apps/defi/src/lang/en.json +++ b/apps/defi/src/lang/en.json @@ -53,6 +53,12 @@ "value": "Connect" } ], + "/0TOL5": [ + { + "type": 0, + "value": "Amount" + } + ], "/6/sPX": [ { "type": 0, @@ -223,6 +229,12 @@ "value": "Return to Home Page" } ], + "2+4p9v": [ + { + "type": 0, + "value": "Claim tab" + } + ], "2/2yg+": [ { "type": 0, @@ -241,6 +253,12 @@ "value": "Powered by Chainlink CCIP" } ], + "2MrktG": [ + { + "type": 0, + "value": "~1 min" + } + ], "2NfxfO": [ { "type": 0, @@ -259,12 +277,6 @@ "value": "Liquid staking" } ], - "2W3kP3": [ - { - "type": 0, - "value": "~1min" - } - ], "2ahSeJ": [ { "type": 0, @@ -277,12 +289,6 @@ "value": "Enable rebasing" } ], - "3Lr8o5": [ - { - "type": 0, - "value": "Larger redemptions coming soon" - } - ], "3PhHPe": [ { "type": 0, @@ -867,12 +873,6 @@ "value": "Change" } ], - "BhDX51": [ - { - "type": 0, - "value": "No Lockups" - } - ], "BnSeXp": [ { "type": 0, @@ -1707,6 +1707,12 @@ "value": "Select lockup" } ], + "RR8vve": [ + { + "type": 0, + "value": "Redeem via the ARM" + } + ], "RVH0u3": [ { "type": 0, @@ -1773,6 +1779,12 @@ "value": "Custom" } ], + "SsufnP": [ + { + "type": 0, + "value": "Withdrawal request successfully sent" + } + ], "SzA4oV": [ { "offset": 0, @@ -1905,12 +1917,6 @@ "value": "You are lawfully permitted to access this site. You understand and accept the risks associated with using the products in this dapp (OETH, OUSD, etc.)" } ], - "UMJuaW": [ - { - "type": 0, - "value": "Your APY:" - } - ], "UkXeBW": [ { "type": 0, @@ -2261,12 +2267,48 @@ "value": "Add to stake" } ], + "cXVyuA": [ + { + "type": 0, + "value": "Your request to withdraw " + }, + { + "type": 1, + "value": "amountOut" + }, + { + "type": 0, + "value": " " + }, + { + "type": 1, + "value": "symbolOut" + }, + { + "type": 0, + "value": " from " + }, + { + "type": 1, + "value": "symbolIn" + }, + { + "type": 0, + "value": " has been sent. Check the Claim tab to view your withdrawal requests." + } + ], "cg1VJ2": [ { "type": 0, "value": "Connect Wallet" } ], + "cn8bYe": [ + { + "type": 0, + "value": "~10 days" + } + ], "d0kJUi": [ { "type": 0, @@ -2347,6 +2389,12 @@ "value": "Connect your wallet to see your balances" } ], + "e61Jf3": [ + { + "type": 0, + "value": "Coming soon" + } + ], "e6Ph5+": [ { "type": 0, @@ -2651,6 +2699,12 @@ "value": "Stake OGN" } ], + "kJmZxj": [ + { + "type": 0, + "value": "Instant or async" + } + ], "kWMpjI": [ { "type": 0, @@ -2941,6 +2995,12 @@ "value": "Swap" } ], + "sjKCFv": [ + { + "type": 0, + "value": "Approximate gas cost:" + } + ], "stTYBM": [ { "type": 0, diff --git a/apps/defi/src/lang/extracts/en.json b/apps/defi/src/lang/extracts/en.json index f4d35740a..ba11e7e79 100644 --- a/apps/defi/src/lang/extracts/en.json +++ b/apps/defi/src/lang/extracts/en.json @@ -26,6 +26,9 @@ "+vVZ/G": { "defaultMessage": "Connect" }, + "/0TOL5": { + "defaultMessage": "Amount" + }, "/6/sPX": { "defaultMessage": "Docs" }, @@ -95,6 +98,9 @@ "1nxJrQ": { "defaultMessage": "Return to Home Page" }, + "2+4p9v": { + "defaultMessage": "Claim tab" + }, "2/2yg+": { "defaultMessage": "Add" }, @@ -104,6 +110,9 @@ "2CoE53": { "defaultMessage": "Powered by Chainlink CCIP" }, + "2MrktG": { + "defaultMessage": "~1 min" + }, "2NfxfO": { "defaultMessage": "Impossible to execute" }, @@ -113,18 +122,12 @@ "2R/YHR": { "defaultMessage": "Liquid staking" }, - "2W3kP3": { - "defaultMessage": "~1min" - }, "2ahSeJ": { "defaultMessage": "OETH analytics" }, "2zUGfB": { "defaultMessage": "Enable rebasing" }, - "3Lr8o5": { - "defaultMessage": "Larger redemptions coming soon" - }, "3PhHPe": { "defaultMessage": "The variable APY currently being earned on staked xOGN." }, @@ -344,9 +347,6 @@ "BY343C": { "defaultMessage": "Change" }, - "BhDX51": { - "defaultMessage": "No Lockups" - }, "BnSeXp": { "defaultMessage": "Decreasing lock-up duration decreases APY and the amount of xOGN you will receive." }, @@ -671,6 +671,9 @@ "RIV67a": { "defaultMessage": "Select lockup" }, + "RR8vve": { + "defaultMessage": "Redeem via the ARM" + }, "RVH0u3": { "defaultMessage": "Delegating Voting Power" }, @@ -704,6 +707,9 @@ "Sjo1P4": { "defaultMessage": "Custom" }, + "SsufnP": { + "defaultMessage": "Withdrawal request successfully sent" + }, "SzA4oV": { "defaultMessage": "{count,plural,=0{No address} =1{# address} other{# addresses}}" }, @@ -731,9 +737,6 @@ "ULVduL": { "defaultMessage": "You are lawfully permitted to access this site. You understand and accept the risks associated with using the products in this dapp (OETH, OUSD, etc.)" }, - "UMJuaW": { - "defaultMessage": "Your APY:" - }, "UkXeBW": { "defaultMessage": "If the problem persists, you can contact us through our {support}." }, @@ -881,9 +884,15 @@ "cWvi0w": { "defaultMessage": "Add to stake" }, + "cXVyuA": { + "defaultMessage": "Your request to withdraw {amountOut} {symbolOut} from {symbolIn} has been sent. Check the Claim tab to view your withdrawal requests." + }, "cg1VJ2": { "defaultMessage": "Connect Wallet" }, + "cn8bYe": { + "defaultMessage": "~10 days" + }, "d0kJUi": { "defaultMessage": "Connect your wallet to see your voting power" }, @@ -917,6 +926,9 @@ "e+yfm6": { "defaultMessage": "Connect your wallet to see your balances" }, + "e61Jf3": { + "defaultMessage": "Coming soon" + }, "e6Ph5+": { "defaultMessage": "Address" }, @@ -1049,6 +1061,9 @@ "kH1R79": { "defaultMessage": "Stake OGN" }, + "kJmZxj": { + "defaultMessage": "Instant or async" + }, "kWMpjI": { "defaultMessage": "Available on" }, @@ -1169,6 +1184,9 @@ "s8BnAC": { "defaultMessage": "Swap" }, + "sjKCFv": { + "defaultMessage": "Approximate gas cost:" + }, "stTYBM": { "defaultMessage": "You confirm that you are not a resident of, citizen of, located in, incorporated in, or have a registered office in the United States or any country or region currently currently subject to sanctions by the United States." }, diff --git a/libs/defi/oeth/src/redeem/components/Swapper.tsx b/libs/defi/oeth/src/redeem/components/Swapper.tsx index 76c8f2b03..302f02a33 100644 --- a/libs/defi/oeth/src/redeem/components/Swapper.tsx +++ b/libs/defi/oeth/src/redeem/components/Swapper.tsx @@ -1,3 +1,5 @@ +import { useState } from 'react'; + import { Button, Card, @@ -48,12 +50,15 @@ import { useIntl } from 'react-intl'; import { useAccount } from 'wagmi'; import { RedeemActionCard } from './RedeemActionCard'; +import { WithdrawalRequestModal } from './WithdrawalRequestModal'; import type { StackProps } from '@mui/material'; import type { Activity } from '@origin/defi/shared'; import type { SwapState } from '@origin/shared/providers'; import type { Dnum } from 'dnum'; +import type { WithdrawalRequestModalProps } from './WithdrawalRequestModal'; + export type SwapperProps = Pick< SwapState, 'swapActions' | 'swapRoutes' | 'trackEvent' @@ -73,6 +78,8 @@ export const Swapper = ({ const pushActivity = usePushActivity(); const updateActivity = useUpdateActivity(); const deleteActivity = useDeleteActivity(); + const [open, setOpen] = useState(false); + const [info, setInfo] = useState>(); return ( { + onSwapSuccess={({ + amountOut, + tokenIn, + tokenOut, + trackId, + txReceipt, + notifId, + }) => { + setInfo({ + amountOut, + tokenIn, + tokenOut, + txReceipt, + }); + setOpen(true); deleteNotification(notifId); const updated = updateActivity({ id: trackId, @@ -228,6 +249,15 @@ export const Swapper = ({ }} > + { + setOpen(false); + }} + keepMounted={false} + {...info} + /> ); }; @@ -435,7 +465,9 @@ function SwapperWrapped({ defaultMessage: 'Waiting for signature', }) ) : isApprovalLoading ? ( - intl.formatMessage({ defaultMessage: 'Processing Approval' }) + intl.formatMessage({ + defaultMessage: 'Processing Approval', + }) ) : ( intl.formatMessage({ defaultMessage: 'Approve' }) )} @@ -451,9 +483,13 @@ function SwapperWrapped({ {isSwapRoutesLoading ? ( ) : isSwapWaitingForSignature ? ( - intl.formatMessage({ defaultMessage: 'Waiting for signature' }) + intl.formatMessage({ + defaultMessage: 'Waiting for signature', + }) ) : isSwapLoading ? ( - intl.formatMessage({ defaultMessage: 'Processing Transaction' }) + intl.formatMessage({ + defaultMessage: 'Processing Transaction', + }) ) : ( swapButtonLabel )} diff --git a/libs/defi/oeth/src/redeem/components/WithdrawalRequestModal.tsx b/libs/defi/oeth/src/redeem/components/WithdrawalRequestModal.tsx new file mode 100644 index 000000000..9609303bd --- /dev/null +++ b/libs/defi/oeth/src/redeem/components/WithdrawalRequestModal.tsx @@ -0,0 +1,117 @@ +import { + Box, + Button, + Dialog, + DialogContent, + DialogTitle, + IconButton, + Stack, + Typography, + useMediaQuery, + useTheme, +} from '@mui/material'; +import { FaCheckRegular, FaXmarkRegular } from '@origin/shared/icons'; +import { BlockExplorerLink } from '@origin/shared/providers'; +import { getFormatPrecision } from '@origin/shared/utils'; +import { format } from 'dnum'; +import { useIntl } from 'react-intl'; + +import { useViewSelect } from '../hooks'; + +import type { DialogProps } from '@mui/material'; +import type { Token } from '@origin/shared/contracts'; +import type { Dnum } from 'dnum'; +import type { TransactionReceipt } from 'viem'; + +export type WithdrawalRequestModalProps = { + amountOut?: bigint; + tokenIn?: Token; + tokenOut?: Token; + txReceipt?: TransactionReceipt; +} & DialogProps; + +export const WithdrawalRequestModal = ({ + amountOut, + tokenIn, + tokenOut, + txReceipt, + onClose, + ...rest +}: WithdrawalRequestModalProps) => { + const intl = useIntl(); + const theme = useTheme(); + const fullScreen = useMediaQuery(theme.breakpoints.down('md')); + const { update } = useViewSelect(); + + const handleClaimClick = () => { + update('claim'); + onClose?.({}, 'backdropClick'); + }; + + const amt = [amountOut ?? 0n, tokenOut?.decimals ?? 18] as Dnum; + + return ( + + + { + onClose?.(evt, 'backdropClick'); + }} + > + + + + + + + + + + {intl.formatMessage({ + defaultMessage: 'Withdrawal request successfully sent', + })} + + + {intl.formatMessage( + { + defaultMessage: + 'Your request to withdraw {amountOut} {symbolOut} from {symbolIn} has been sent. Check the Claim tab to view your withdrawal requests.', + }, + { + amountOut: format(amt, getFormatPrecision(amt)), + symbolIn: tokenIn?.symbol ?? '', + symbolOut: tokenOut?.symbol ?? '', + }, + )} + + + {txReceipt && } + + + + ); +}; From 4e4fdcea7d0a54b7260ad8e0d0b249c89759a8a0 Mon Sep 17 00:00:00 2001 From: toniocodo Date: Wed, 10 Jul 2024 20:49:01 +0200 Subject: [PATCH 04/33] =?UTF-8?q?feat:=20add=20claim=20view,=20plug=20to?= =?UTF-8?q?=20squid=20999,=20update=20schema=20WIP=F0=9F=9A=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env | 7 +- .graphqlconfig | 2 +- apps/defi/.env | 3 +- libs/defi/oeth/src/redeem/actions/index.ts | 2 +- .../oeth/src/redeem/components/ClaimForm.tsx | 241 ++++++++++++++++++ .../src/redeem/components/ClaimHeader.tsx | 134 ++++++++++ .../oeth/src/redeem/components/Swapper.tsx | 38 ++- .../oeth/src/redeem/components/ViewSwitch.tsx | 20 +- .../components/WithdrawalRequestModal.tsx | 4 +- libs/defi/oeth/src/redeem/constants.ts | 2 +- libs/defi/oeth/src/redeem/hooks.ts | 64 +++++ .../defi/oeth/src/redeem/queries.generated.ts | 48 ++++ libs/defi/oeth/src/redeem/queries.graphql | 12 + libs/defi/oeth/src/redeem/types.ts | 11 + libs/defi/oeth/src/redeem/views/ClaimView.tsx | 15 +- .../defi/oeth/src/redeem/views/RedeemView.tsx | 4 +- .../src/components/Activities/constants.tsx | 42 +++ .../shared/src/components/Activities/types.ts | 7 + libs/defi/shared/src/generated/graphql.ts | 194 ++++++++++++++ .../shared/src/generated/graphql.ts | 194 ++++++++++++++ libs/oeth/shared/src/generated/graphql.ts | 194 ++++++++++++++ libs/ousd/shared/src/generated/graphql.ts | 194 ++++++++++++++ 22 files changed, 1397 insertions(+), 35 deletions(-) create mode 100644 libs/defi/oeth/src/redeem/components/ClaimForm.tsx create mode 100644 libs/defi/oeth/src/redeem/components/ClaimHeader.tsx create mode 100644 libs/defi/oeth/src/redeem/queries.generated.ts create mode 100644 libs/defi/oeth/src/redeem/queries.graphql diff --git a/.env b/.env index fbb63d96e..c074d3049 100644 --- a/.env +++ b/.env @@ -1,11 +1,16 @@ +# TODO remove after tenderly testing # graphql Subsquid endpoint -VITE_SUBSQUID_URL="https://origin.squids.live/origin-squid/graphql" +VITE_SUBSQUID_URL="https://origin.squids.live/origin-squid/v/v999/graphql" + # graphql Snapshot endpoint VITE_SNAPSHOT_URL="https://hub.snapshot.org/graphql" + # Alchemy rpc url VITE_ALCHEMY_RPC="https://eth-mainnet.g.alchemy.com/v2/" + # Alchemy arbitrum rpc url VITE_ALCHEMY_ARBITRUM_RPC="https://arb-mainnet.g.alchemy.com/v2/" + # Nx 18 enables using plugins to infer targets by default # This is disabled for existing workspaces to maintain compatibility # For more info, see: https://nx.dev/concepts/inferred-tasks diff --git a/.graphqlconfig b/.graphqlconfig index 8d5a1274d..eb5162dc6 100644 --- a/.graphqlconfig +++ b/.graphqlconfig @@ -1,7 +1,7 @@ { "name": "Subsquid GraphQL Schema", "schemaPath": [ - "https://origin.squids.live/origin-squid/graphql", + "https://origin.squids.live/origin-squid/v/v999/graphql", "https://origin.squids.live/prime-eth-squid/graphql", "https://hub.snapshot.org/graphql" ] diff --git a/apps/defi/.env b/apps/defi/.env index 9ea258cf4..e6a37e392 100644 --- a/apps/defi/.env +++ b/apps/defi/.env @@ -1,5 +1,6 @@ +# TODO remove after tenderly testing # Set this to any custom RPC to override public endpoint -VITE_CUSTOM_RPC= +VITE_CUSTOM_RPC="https://virtual.mainnet.rpc.tenderly.co/e6243bfa-8701-4c53-af2b-ba435081669a" # Wallet Connect v2 project id VITE_WALLET_CONNECT_PROJECT_ID= diff --git a/libs/defi/oeth/src/redeem/actions/index.ts b/libs/defi/oeth/src/redeem/actions/index.ts index b3a55397c..cee1db918 100644 --- a/libs/defi/oeth/src/redeem/actions/index.ts +++ b/libs/defi/oeth/src/redeem/actions/index.ts @@ -78,6 +78,6 @@ export const redeemActions: Record = { ...defaultApi, ...redeemVaultAsync, routeLabel: defineMessage({ defaultMessage: 'Redeem via OETH Vault' }), - buttonLabel: defineMessage({ defaultMessage: 'Redeem' }), + buttonLabel: defineMessage({ defaultMessage: 'Request withdrawal' }), }, }; diff --git a/libs/defi/oeth/src/redeem/components/ClaimForm.tsx b/libs/defi/oeth/src/redeem/components/ClaimForm.tsx new file mode 100644 index 000000000..f3a94d36f --- /dev/null +++ b/libs/defi/oeth/src/redeem/components/ClaimForm.tsx @@ -0,0 +1,241 @@ +import { useMemo, useState } from 'react'; + +import { + Checkbox, + CircularProgress, + Collapse, + Divider, + FormControlLabel, + Stack, + Typography, +} from '@mui/material'; +import { SectionCard, useTxButton } from '@origin/defi/shared'; +import { ValueLabel } from '@origin/shared/components'; +import { contracts, tokens } from '@origin/shared/contracts'; +import { FaCircleCheckRegular, FaClockRegular } from '@origin/shared/icons'; +import { TxButton } from '@origin/shared/providers'; +import { + getFormatPrecision, + isNilOrEmpty, + ZERO_ADDRESS, +} from '@origin/shared/utils'; +import { useQueryClient } from '@tanstack/react-query'; +import { add, eq, format, from } from 'dnum'; +import { remove } from 'ramda'; +import { useIntl } from 'react-intl'; +import { useAccount } from 'wagmi'; + +import { useWithdrawalRequests } from '../hooks'; +import { useWithdrawalRequestsQuery } from '../queries.generated'; + +import type { StackProps } from '@mui/material'; +import type { Dnum } from 'dnum'; + +import type { WithdrawalRequest } from '../types'; + +export const ClaimForm = (props: StackProps) => { + const intl = useIntl(); + const queryClient = useQueryClient(); + const { address } = useAccount(); + const [selectedClaimIds, setSelectedClaimIds] = useState([]); + const { data: requests, isLoading: isRequestsLoading } = + useWithdrawalRequests({ + select: (data) => data?.filter((r) => !r.claimed), + }); + const args = + selectedClaimIds.length === 1 + ? { + contract: contracts.mainnet.OETHVault, + functionName: 'claimWithdrawal', + args: [selectedClaimIds[0]], + } + : { + contract: contracts.mainnet.OETHVault, + functionName: 'claimWithdrawals', + args: selectedClaimIds, + }; + + const selectedAmount = useMemo( + () => + selectedClaimIds.reduce((acc, curr) => { + const req = requests?.find((r) => r.requestId === curr); + + return add([req?.amount ?? 0n, tokens.mainnet.WETH.decimals], acc); + }, from(0)), + [requests, selectedClaimIds], + ); + const { params, callbacks, gasPrice, isWriteGasLoading } = useTxButton({ + params: args as any, + callbacks: { + onWriteSuccess: () => { + queryClient.invalidateQueries({ + queryKey: [ + useWithdrawalRequestsQuery.getKey({ + address: address ?? ZERO_ADDRESS, + }), + ], + }); + }, + }, + activity: { + type: 'claim-withdrawal', + status: 'idle', + amountIn: selectedAmount[0], + tokenIdIn: tokens.mainnet.WETH.id, + }, + enableGas: true, + }); + + const handleClaimClick = (requestId: bigint) => () => { + const idx = selectedClaimIds.findIndex((id) => id === requestId); + if (idx === -1) { + setSelectedClaimIds((prev) => [...prev, requestId]); + } else { + setSelectedClaimIds((prev) => remove(idx, 1, prev)); + } + }; + + return ( + + + }> + {isRequestsLoading ? ( + + + + ) : isNilOrEmpty(requests) ? ( + + + {intl.formatMessage({ + defaultMessage: 'You have no withdrawal requests', + })} + + + ) : ( + requests?.map((r) => ( + + )) + )} + + + + + + + + ); +}; + +type ClaimRowProps = { + request: WithdrawalRequest; + selected: boolean; + onSelect: () => void; +} & StackProps; + +const ClaimRow = ({ request, selected, onSelect, ...rest }: ClaimRowProps) => { + const amt = [request?.amount ?? 0n, tokens.mainnet.WETH.decimals] as Dnum; + + return ( + + } + label={ + + + {format(amt, getFormatPrecision(amt))} + + + {tokens.mainnet.WETH.symbol} + + + } + onChange={onSelect} + disabled={!request.claimable} + disableTypography + /> + + + ); +}; + +type ClaimChipProps = { claimable: boolean } & StackProps; + +const ClaimChip = ({ claimable, ...rest }: ClaimChipProps) => { + const intl = useIntl(); + + const icon = claimable ? ( + + ) : ( + + ); + const label = claimable + ? intl.formatMessage({ defaultMessage: 'Ready' }) + : intl.formatMessage({ defaultMessage: 'Pending' }); + + return ( + + {icon} + + {label} + + + ); +}; diff --git a/libs/defi/oeth/src/redeem/components/ClaimHeader.tsx b/libs/defi/oeth/src/redeem/components/ClaimHeader.tsx new file mode 100644 index 000000000..376a3a3d4 --- /dev/null +++ b/libs/defi/oeth/src/redeem/components/ClaimHeader.tsx @@ -0,0 +1,134 @@ +import { Divider, Stack, Typography } from '@mui/material'; +import { LoadingLabel } from '@origin/shared/components'; +import { tokens } from '@origin/shared/contracts'; +import { FaCircleCheckRegular, FaClockRegular } from '@origin/shared/icons'; +import { getFormatPrecision } from '@origin/shared/utils'; +import { add, eq, format, from } from 'dnum'; +import { groupBy } from 'ramda'; +import { useIntl } from 'react-intl'; + +import { useWithdrawalRequests } from '../hooks'; + +import type { StackProps } from '@mui/material'; + +export const ClaimHeader = (props: StackProps) => { + const intl = useIntl(); + const { data: requests, isLoading: isRequestsLoading } = + useWithdrawalRequests({ + select: (data) => data?.filter((r) => !r.claimed), + }); + + const { claimable, pending } = groupBy( + (r) => (r.claimable ? 'claimable' : 'pending'), + requests ?? [], + ); + const availableToClaim = + claimable?.reduce( + (acc, curr) => + curr.claimable + ? add([curr.amount, tokens.mainnet.WETH.decimals], acc) + : acc, + from(0), + ) ?? from(0); + const pendingAmount = + pending?.reduce( + (acc, curr) => + curr.claimable + ? add([curr.amount, tokens.mainnet.WETH.decimals], acc) + : acc, + from(0), + ) ?? from(0); + + return ( + + + + {intl.formatMessage({ defaultMessage: 'Available to claim' })} + + + + {eq(availableToClaim, 0) + ? '0.0' + : format(availableToClaim, getFormatPrecision(availableToClaim))} + + {tokens.mainnet.WETH.symbol} + + + + + + + {intl.formatMessage({ defaultMessage: 'Your requests' })} + + + + + + + + + + + {intl.formatMessage({ defaultMessage: 'Your pending amount' })} + + + + {format(pendingAmount, getFormatPrecision(pendingAmount))} + + + {tokens.mainnet.OETH.symbol} + + + + + + ); +}; + +type IconChipProps = { + claimable: boolean; + amount: number; +} & StackProps; + +const IconChip = ({ claimable, amount, ...rest }: IconChipProps) => { + return ( + + {claimable ? : } + {amount} + + ); +}; diff --git a/libs/defi/oeth/src/redeem/components/Swapper.tsx b/libs/defi/oeth/src/redeem/components/Swapper.tsx index 302f02a33..369d440a0 100644 --- a/libs/defi/oeth/src/redeem/components/Swapper.tsx +++ b/libs/defi/oeth/src/redeem/components/Swapper.tsx @@ -23,6 +23,7 @@ import { ErrorBoundary, ErrorCard, LoadingLabel, + ValueLabel, } from '@origin/shared/components'; import { ConnectedButton, @@ -376,7 +377,7 @@ function SwapperWrapped({ }} /> - {intl.formatMessage({ defaultMessage: 'Instant or async' })} + {intl.formatMessage({ defaultMessage: 'Duration' })} @@ -425,28 +426,25 @@ function SwapperWrapped({ 0n}> - - - {intl.formatMessage({ - defaultMessage: 'Approximate gas cost:', - })} - - - - ${format(gasPrice?.gasCostUsd ?? from(0), 2)} - - - + labelProps={{ + variant: 'body3', + fontWeight: 'medium', + }} + /> diff --git a/libs/defi/oeth/src/redeem/components/ViewSwitch.tsx b/libs/defi/oeth/src/redeem/components/ViewSwitch.tsx index c27b0eb1a..0337a2703 100644 --- a/libs/defi/oeth/src/redeem/components/ViewSwitch.tsx +++ b/libs/defi/oeth/src/redeem/components/ViewSwitch.tsx @@ -1,8 +1,9 @@ import { Stack } from '@mui/material'; import { SliderSwitch } from '@origin/shared/components'; +import { isNilOrEmpty } from '@origin/shared/utils'; import { useIntl } from 'react-intl'; -import { useViewSelect } from '../hooks'; +import { useViewSelect, useWithdrawalRequests } from '../hooks'; import type { StackProps } from '@mui/material'; import type { Option } from '@origin/shared/components'; @@ -10,6 +11,10 @@ import type { Option } from '@origin/shared/components'; export const ViewSwitch = (props: StackProps) => { const intl = useIntl(); const { view, update } = useViewSelect(); + const { data: claimableRequests, isLoading: isClaimableRequestsLoading } = + useWithdrawalRequests({ + select: (data) => data?.filter?.((r) => r.claimable), + }); const handleChange = (newVal: string | number) => { update(newVal as 'request' | 'claim'); @@ -20,7 +25,18 @@ export const ViewSwitch = (props: StackProps) => { label: intl.formatMessage({ defaultMessage: 'Request' }), value: 'request', }, - { label: intl.formatMessage({ defaultMessage: 'Claim' }), value: 'claim' }, + { + label: intl.formatMessage( + { defaultMessage: 'Claim{amount}' }, + { + amount: + isClaimableRequestsLoading || isNilOrEmpty(claimableRequests) + ? '' + : ` (${claimableRequests?.length})`, + }, + ), + value: 'claim', + }, ]; return ( diff --git a/libs/defi/oeth/src/redeem/components/WithdrawalRequestModal.tsx b/libs/defi/oeth/src/redeem/components/WithdrawalRequestModal.tsx index 9609303bd..69a8ae2eb 100644 --- a/libs/defi/oeth/src/redeem/components/WithdrawalRequestModal.tsx +++ b/libs/defi/oeth/src/redeem/components/WithdrawalRequestModal.tsx @@ -107,7 +107,9 @@ export const WithdrawalRequestModal = ({ size="large" sx={{ mb: 3 }} > - {intl.formatMessage({ defaultMessage: 'Claim tab' })} + {intl.formatMessage({ + defaultMessage: 'View your withdrawal requests', + })} {txReceipt && } diff --git a/libs/defi/oeth/src/redeem/constants.ts b/libs/defi/oeth/src/redeem/constants.ts index 8d44f3567..4e42f289c 100644 --- a/libs/defi/oeth/src/redeem/constants.ts +++ b/libs/defi/oeth/src/redeem/constants.ts @@ -35,7 +35,7 @@ export const redeemRoutes: SwapRoute[] = [ action: 'redeem-vault-async', meta: { icon: OETH, - waitTime: defineMessage({ defaultMessage: '~10 days' }), + waitTime: defineMessage({ defaultMessage: '~a few days' }), }, }, ]; diff --git a/libs/defi/oeth/src/redeem/hooks.ts b/libs/defi/oeth/src/redeem/hooks.ts index c8f405f70..c2bc99552 100644 --- a/libs/defi/oeth/src/redeem/hooks.ts +++ b/libs/defi/oeth/src/redeem/hooks.ts @@ -1,6 +1,18 @@ import { useMemo } from 'react'; +import { contracts } from '@origin/shared/contracts'; +import { isFulfilled, ZERO_ADDRESS } from '@origin/shared/utils'; +import { useQuery, useQueryClient } from '@tanstack/react-query'; +import { readContract } from '@wagmi/core'; import { useSearchParams } from 'react-router-dom'; +import { useAccount, useConfig } from 'wagmi'; + +import { useWithdrawalRequestsQuery } from './queries.generated'; + +import type { HexAddress } from '@origin/shared/utils'; +import type { UseQueryOptions } from '@tanstack/react-query'; + +import type { WithdrawalRequest } from './types'; export const useViewSelect = () => { const [search, setSearch] = useSearchParams({ @@ -20,3 +32,55 @@ export const useViewSelect = () => { [search, setSearch], ); }; + +export const useWithdrawalRequests = ( + options?: Omit< + UseQueryOptions< + WithdrawalRequest[], + Error, + WithdrawalRequest[], + ['useClaimableRequests', HexAddress | undefined] + >, + 'queryKey' | 'queryFn' + >, +) => { + const { address } = useAccount(); + const config = useConfig(); + const queryClient = useQueryClient(); + + return useQuery({ + ...options, + queryKey: ['useClaimableRequests', address], + queryFn: async () => { + const res = await Promise.allSettled([ + readContract(config, { + address: contracts.mainnet.OETHVault.address, + abi: contracts.mainnet.OETHVault.abi, + functionName: 'withdrawalQueueMetadata', + chainId: contracts.mainnet.OETHVault.chainId, + }), + queryClient.fetchQuery({ + queryKey: useWithdrawalRequestsQuery.getKey({ + address: address ?? ZERO_ADDRESS, + }), + queryFn: useWithdrawalRequestsQuery.fetcher({ + address: address ?? ZERO_ADDRESS, + }), + }), + ]); + const queueData = isFulfilled(res[0]) ? res[0].value : null; + const requests = isFulfilled(res[1]) + ? res[1].value?.oethWithdrawalRequests ?? [] + : []; + + return requests.map((r) => ({ + ...r, + requestId: BigInt(r.requestId), + amount: BigInt(r.amount), + queued: BigInt(r.queued), + claimable: + !r.claimed && BigInt(r.queued) <= BigInt(queueData?.claimable ?? 0), + })); + }, + }); +}; diff --git a/libs/defi/oeth/src/redeem/queries.generated.ts b/libs/defi/oeth/src/redeem/queries.generated.ts new file mode 100644 index 000000000..2f06336c3 --- /dev/null +++ b/libs/defi/oeth/src/redeem/queries.generated.ts @@ -0,0 +1,48 @@ +import * as Types from '@origin/defi/shared'; + +import { useQuery, UseQueryOptions } from '@tanstack/react-query'; +import { graphqlClient } from '@origin/defi/shared'; +export type WithdrawalRequestsQueryVariables = Types.Exact<{ + address: Types.Scalars['String']['input']; +}>; + + +export type WithdrawalRequestsQuery = { __typename?: 'Query', oethWithdrawalRequests: Array<{ __typename?: 'OETHWithdrawalRequest', id: string, requestId: string, timestamp: string, amount: string, queued: string, claimed: boolean, blockNumber: number }> }; + + + +export const WithdrawalRequestsDocument = ` + query WithdrawalRequests($address: String!) { + oethWithdrawalRequests(where: {withdrawer_containsInsensitive: $address}) { + id + requestId + timestamp + amount + queued + claimed + blockNumber + requestId + } +} + `; + +export const useWithdrawalRequestsQuery = < + TData = WithdrawalRequestsQuery, + TError = unknown + >( + variables: WithdrawalRequestsQueryVariables, + options?: Omit, 'queryKey'> & { queryKey?: UseQueryOptions['queryKey'] } + ) => { + + return useQuery( + { + queryKey: ['WithdrawalRequests', variables], + queryFn: graphqlClient(WithdrawalRequestsDocument, variables), + ...options + } + )}; + +useWithdrawalRequestsQuery.getKey = (variables: WithdrawalRequestsQueryVariables) => ['WithdrawalRequests', variables]; + + +useWithdrawalRequestsQuery.fetcher = (variables: WithdrawalRequestsQueryVariables, options?: RequestInit['headers']) => graphqlClient(WithdrawalRequestsDocument, variables, options); diff --git a/libs/defi/oeth/src/redeem/queries.graphql b/libs/defi/oeth/src/redeem/queries.graphql new file mode 100644 index 000000000..62f59ac39 --- /dev/null +++ b/libs/defi/oeth/src/redeem/queries.graphql @@ -0,0 +1,12 @@ +query WithdrawalRequests($address: String!) { + oethWithdrawalRequests(where: { withdrawer_containsInsensitive: $address }) { + id + requestId + timestamp + amount + queued + claimed + blockNumber + requestId + } +} diff --git a/libs/defi/oeth/src/redeem/types.ts b/libs/defi/oeth/src/redeem/types.ts index 3e40efc18..214ed0f8f 100644 --- a/libs/defi/oeth/src/redeem/types.ts +++ b/libs/defi/oeth/src/redeem/types.ts @@ -13,3 +13,14 @@ export type OethRedeemAction = | 'redeem-vault' | 'redeem-vault-async' | 'swap-curve'; + +export type WithdrawalRequest = { + id: string; + requestId: bigint; + timestamp: string; + amount: bigint; + queued: bigint; + claimed: boolean; + blockNumber: number; + claimable: boolean; +}; diff --git a/libs/defi/oeth/src/redeem/views/ClaimView.tsx b/libs/defi/oeth/src/redeem/views/ClaimView.tsx index c04dd2048..dcd1aa63f 100644 --- a/libs/defi/oeth/src/redeem/views/ClaimView.tsx +++ b/libs/defi/oeth/src/redeem/views/ClaimView.tsx @@ -1,10 +1,15 @@ -import { Typography } from '@mui/material'; -import { useIntl } from 'react-intl'; +import { Card, CardContent } from '@mui/material'; -export const ClaimView = () => { - const intl = useIntl(); +import { ClaimForm } from '../components/ClaimForm'; +import { ClaimHeader } from '../components/ClaimHeader'; +export const ClaimView = () => { return ( - {intl.formatMessage({ defaultMessage: 'Claim' })} + + + + + + ); }; diff --git a/libs/defi/oeth/src/redeem/views/RedeemView.tsx b/libs/defi/oeth/src/redeem/views/RedeemView.tsx index 1b29756d6..43375ab4c 100644 --- a/libs/defi/oeth/src/redeem/views/RedeemView.tsx +++ b/libs/defi/oeth/src/redeem/views/RedeemView.tsx @@ -28,8 +28,8 @@ export const RedeemView = () => { token={tokens.mainnet.OETH} /> - - + + } diff --git a/libs/defi/shared/src/components/Activities/constants.tsx b/libs/defi/shared/src/components/Activities/constants.tsx index 8e1495842..7ea3e610b 100644 --- a/libs/defi/shared/src/components/Activities/constants.tsx +++ b/libs/defi/shared/src/components/Activities/constants.tsx @@ -24,6 +24,7 @@ import type { ApprovalActivity, BridgeActivity, ClaimRewardsActivity, + ClaimWithdrawalActivity, DelegateVoteActivity, ExtendStakeActivity, MigrateActivity, @@ -191,6 +192,47 @@ export const activityOptions: Record = { ); }, }, + 'claim-withdrawal': { + title: (activity, intl) => + ({ + pending: intl.formatMessage({ defaultMessage: 'Claiming Withdrawal' }), + signed: intl.formatMessage({ defaultMessage: 'Claiming Withdrawal' }), + success: intl.formatMessage({ defaultMessage: 'Claimed Withdrawal' }), + error: intl.formatMessage({ + defaultMessage: 'Error while claiming withdrawal', + }), + idle: intl.formatMessage({ defaultMessage: 'Claim Withdrawal' }), + })[activity.status], + subtitle: (activity, intl) => { + const { amountIn, tokenIdIn } = activity as ClaimWithdrawalActivity; + const tokenIn = getTokenById(tokenIdIn); + const amount = format([amountIn ?? 0n, tokenIn.decimals ?? 18], 4); + + return intl.formatMessage( + { + defaultMessage: 'Claim {amount} {symbolIn}', + }, + { amount, symbolIn: tokenIn.symbol }, + ); + }, + icon: (activity) => { + const { tokenIdIn } = activity as ClaimRewardsActivity; + const tokenIn = getTokenById(tokenIdIn); + + return ( + + } + badgeBkgColor="primary.main" + > + + + ); + }, + }, delegate: { title: (activity, intl) => ({ diff --git a/libs/defi/shared/src/components/Activities/types.ts b/libs/defi/shared/src/components/Activities/types.ts index 5d4a58fc6..7d75e82b1 100644 --- a/libs/defi/shared/src/components/Activities/types.ts +++ b/libs/defi/shared/src/components/Activities/types.ts @@ -35,6 +35,12 @@ export interface ClaimRewardsActivity extends ActivityBase { amountIn: bigint; } +export interface ClaimWithdrawalActivity extends ActivityBase { + type: 'claim-withdrawal'; + amountIn: bigint; + tokenIdIn: TokenId; +} + export interface DelegateVoteActivity extends ActivityBase { type: 'delegate'; tokenIdIn: TokenId; @@ -105,6 +111,7 @@ export type Activity = | ApprovalActivity | BridgeActivity | ClaimRewardsActivity + | ClaimWithdrawalActivity | DelegateVoteActivity | ExtendStakeActivity | MigrateActivity diff --git a/libs/defi/shared/src/generated/graphql.ts b/libs/defi/shared/src/generated/graphql.ts index 2af37c450..129fedefe 100644 --- a/libs/defi/shared/src/generated/graphql.ts +++ b/libs/defi/shared/src/generated/graphql.ts @@ -9933,6 +9933,169 @@ export type OethVaultsConnection = { totalCount: Scalars['Int']['output']; }; +export type OethWithdrawalRequest = { + __typename?: 'OETHWithdrawalRequest'; + amount: Scalars['BigInt']['output']; + blockNumber: Scalars['Int']['output']; + claimed: Scalars['Boolean']['output']; + id: Scalars['String']['output']; + queued: Scalars['BigInt']['output']; + requestId: Scalars['BigInt']['output']; + timestamp: Scalars['DateTime']['output']; + withdrawer: Scalars['String']['output']; +}; + +export type OethWithdrawalRequestEdge = { + __typename?: 'OETHWithdrawalRequestEdge'; + cursor: Scalars['String']['output']; + node: OethWithdrawalRequest; +}; + +export enum OethWithdrawalRequestOrderByInput { + AmountAsc = 'amount_ASC', + AmountAscNullsFirst = 'amount_ASC_NULLS_FIRST', + AmountAscNullsLast = 'amount_ASC_NULLS_LAST', + AmountDesc = 'amount_DESC', + AmountDescNullsFirst = 'amount_DESC_NULLS_FIRST', + AmountDescNullsLast = 'amount_DESC_NULLS_LAST', + BlockNumberAsc = 'blockNumber_ASC', + BlockNumberAscNullsFirst = 'blockNumber_ASC_NULLS_FIRST', + BlockNumberAscNullsLast = 'blockNumber_ASC_NULLS_LAST', + BlockNumberDesc = 'blockNumber_DESC', + BlockNumberDescNullsFirst = 'blockNumber_DESC_NULLS_FIRST', + BlockNumberDescNullsLast = 'blockNumber_DESC_NULLS_LAST', + ClaimedAsc = 'claimed_ASC', + ClaimedAscNullsFirst = 'claimed_ASC_NULLS_FIRST', + ClaimedAscNullsLast = 'claimed_ASC_NULLS_LAST', + ClaimedDesc = 'claimed_DESC', + ClaimedDescNullsFirst = 'claimed_DESC_NULLS_FIRST', + ClaimedDescNullsLast = 'claimed_DESC_NULLS_LAST', + IdAsc = 'id_ASC', + IdAscNullsFirst = 'id_ASC_NULLS_FIRST', + IdAscNullsLast = 'id_ASC_NULLS_LAST', + IdDesc = 'id_DESC', + IdDescNullsFirst = 'id_DESC_NULLS_FIRST', + IdDescNullsLast = 'id_DESC_NULLS_LAST', + QueuedAsc = 'queued_ASC', + QueuedAscNullsFirst = 'queued_ASC_NULLS_FIRST', + QueuedAscNullsLast = 'queued_ASC_NULLS_LAST', + QueuedDesc = 'queued_DESC', + QueuedDescNullsFirst = 'queued_DESC_NULLS_FIRST', + QueuedDescNullsLast = 'queued_DESC_NULLS_LAST', + RequestIdAsc = 'requestId_ASC', + RequestIdAscNullsFirst = 'requestId_ASC_NULLS_FIRST', + RequestIdAscNullsLast = 'requestId_ASC_NULLS_LAST', + RequestIdDesc = 'requestId_DESC', + RequestIdDescNullsFirst = 'requestId_DESC_NULLS_FIRST', + RequestIdDescNullsLast = 'requestId_DESC_NULLS_LAST', + TimestampAsc = 'timestamp_ASC', + TimestampAscNullsFirst = 'timestamp_ASC_NULLS_FIRST', + TimestampAscNullsLast = 'timestamp_ASC_NULLS_LAST', + TimestampDesc = 'timestamp_DESC', + TimestampDescNullsFirst = 'timestamp_DESC_NULLS_FIRST', + TimestampDescNullsLast = 'timestamp_DESC_NULLS_LAST', + WithdrawerAsc = 'withdrawer_ASC', + WithdrawerAscNullsFirst = 'withdrawer_ASC_NULLS_FIRST', + WithdrawerAscNullsLast = 'withdrawer_ASC_NULLS_LAST', + WithdrawerDesc = 'withdrawer_DESC', + WithdrawerDescNullsFirst = 'withdrawer_DESC_NULLS_FIRST', + WithdrawerDescNullsLast = 'withdrawer_DESC_NULLS_LAST' +} + +export type OethWithdrawalRequestWhereInput = { + AND?: InputMaybe>; + OR?: InputMaybe>; + amount_eq?: InputMaybe; + amount_gt?: InputMaybe; + amount_gte?: InputMaybe; + amount_in?: InputMaybe>; + amount_isNull?: InputMaybe; + amount_lt?: InputMaybe; + amount_lte?: InputMaybe; + amount_not_eq?: InputMaybe; + amount_not_in?: InputMaybe>; + blockNumber_eq?: InputMaybe; + blockNumber_gt?: InputMaybe; + blockNumber_gte?: InputMaybe; + blockNumber_in?: InputMaybe>; + blockNumber_isNull?: InputMaybe; + blockNumber_lt?: InputMaybe; + blockNumber_lte?: InputMaybe; + blockNumber_not_eq?: InputMaybe; + blockNumber_not_in?: InputMaybe>; + claimed_eq?: InputMaybe; + claimed_isNull?: InputMaybe; + claimed_not_eq?: InputMaybe; + id_contains?: InputMaybe; + id_containsInsensitive?: InputMaybe; + id_endsWith?: InputMaybe; + id_eq?: InputMaybe; + id_gt?: InputMaybe; + id_gte?: InputMaybe; + id_in?: InputMaybe>; + id_isNull?: InputMaybe; + id_lt?: InputMaybe; + id_lte?: InputMaybe; + id_not_contains?: InputMaybe; + id_not_containsInsensitive?: InputMaybe; + id_not_endsWith?: InputMaybe; + id_not_eq?: InputMaybe; + id_not_in?: InputMaybe>; + id_not_startsWith?: InputMaybe; + id_startsWith?: InputMaybe; + queued_eq?: InputMaybe; + queued_gt?: InputMaybe; + queued_gte?: InputMaybe; + queued_in?: InputMaybe>; + queued_isNull?: InputMaybe; + queued_lt?: InputMaybe; + queued_lte?: InputMaybe; + queued_not_eq?: InputMaybe; + queued_not_in?: InputMaybe>; + requestId_eq?: InputMaybe; + requestId_gt?: InputMaybe; + requestId_gte?: InputMaybe; + requestId_in?: InputMaybe>; + requestId_isNull?: InputMaybe; + requestId_lt?: InputMaybe; + requestId_lte?: InputMaybe; + requestId_not_eq?: InputMaybe; + requestId_not_in?: InputMaybe>; + timestamp_eq?: InputMaybe; + timestamp_gt?: InputMaybe; + timestamp_gte?: InputMaybe; + timestamp_in?: InputMaybe>; + timestamp_isNull?: InputMaybe; + timestamp_lt?: InputMaybe; + timestamp_lte?: InputMaybe; + timestamp_not_eq?: InputMaybe; + timestamp_not_in?: InputMaybe>; + withdrawer_contains?: InputMaybe; + withdrawer_containsInsensitive?: InputMaybe; + withdrawer_endsWith?: InputMaybe; + withdrawer_eq?: InputMaybe; + withdrawer_gt?: InputMaybe; + withdrawer_gte?: InputMaybe; + withdrawer_in?: InputMaybe>; + withdrawer_isNull?: InputMaybe; + withdrawer_lt?: InputMaybe; + withdrawer_lte?: InputMaybe; + withdrawer_not_contains?: InputMaybe; + withdrawer_not_containsInsensitive?: InputMaybe; + withdrawer_not_endsWith?: InputMaybe; + withdrawer_not_eq?: InputMaybe; + withdrawer_not_in?: InputMaybe>; + withdrawer_not_startsWith?: InputMaybe; + withdrawer_startsWith?: InputMaybe; +}; + +export type OethWithdrawalRequestsConnection = { + __typename?: 'OETHWithdrawalRequestsConnection'; + edges: Array; + pageInfo: PageInfo; + totalCount: Scalars['Int']['output']; +}; + export type OgnStatsResult = { __typename?: 'OGNStatsResult'; circulatingSupply: Scalars['Float']['output']; @@ -16370,6 +16533,11 @@ export type Query = { oethVaultByUniqueInput?: Maybe; oethVaults: Array; oethVaultsConnection: OethVaultsConnection; + oethWithdrawalRequestById?: Maybe; + /** @deprecated Use oethWithdrawalRequestById */ + oethWithdrawalRequestByUniqueInput?: Maybe; + oethWithdrawalRequests: Array; + oethWithdrawalRequestsConnection: OethWithdrawalRequestsConnection; ognStats: OgnStatsResult; ogvAddressById?: Maybe; /** @deprecated Use ogvAddressById */ @@ -18086,6 +18254,32 @@ export type QueryOethVaultsConnectionArgs = { }; +export type QueryOethWithdrawalRequestByIdArgs = { + id: Scalars['String']['input']; +}; + + +export type QueryOethWithdrawalRequestByUniqueInputArgs = { + where: WhereIdInput; +}; + + +export type QueryOethWithdrawalRequestsArgs = { + limit?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe>; + where?: InputMaybe; +}; + + +export type QueryOethWithdrawalRequestsConnectionArgs = { + after?: InputMaybe; + first?: InputMaybe; + orderBy: Array; + where?: InputMaybe; +}; + + export type QueryOgvAddressByIdArgs = { id: Scalars['String']['input']; }; diff --git a/libs/governance/shared/src/generated/graphql.ts b/libs/governance/shared/src/generated/graphql.ts index 2af37c450..129fedefe 100644 --- a/libs/governance/shared/src/generated/graphql.ts +++ b/libs/governance/shared/src/generated/graphql.ts @@ -9933,6 +9933,169 @@ export type OethVaultsConnection = { totalCount: Scalars['Int']['output']; }; +export type OethWithdrawalRequest = { + __typename?: 'OETHWithdrawalRequest'; + amount: Scalars['BigInt']['output']; + blockNumber: Scalars['Int']['output']; + claimed: Scalars['Boolean']['output']; + id: Scalars['String']['output']; + queued: Scalars['BigInt']['output']; + requestId: Scalars['BigInt']['output']; + timestamp: Scalars['DateTime']['output']; + withdrawer: Scalars['String']['output']; +}; + +export type OethWithdrawalRequestEdge = { + __typename?: 'OETHWithdrawalRequestEdge'; + cursor: Scalars['String']['output']; + node: OethWithdrawalRequest; +}; + +export enum OethWithdrawalRequestOrderByInput { + AmountAsc = 'amount_ASC', + AmountAscNullsFirst = 'amount_ASC_NULLS_FIRST', + AmountAscNullsLast = 'amount_ASC_NULLS_LAST', + AmountDesc = 'amount_DESC', + AmountDescNullsFirst = 'amount_DESC_NULLS_FIRST', + AmountDescNullsLast = 'amount_DESC_NULLS_LAST', + BlockNumberAsc = 'blockNumber_ASC', + BlockNumberAscNullsFirst = 'blockNumber_ASC_NULLS_FIRST', + BlockNumberAscNullsLast = 'blockNumber_ASC_NULLS_LAST', + BlockNumberDesc = 'blockNumber_DESC', + BlockNumberDescNullsFirst = 'blockNumber_DESC_NULLS_FIRST', + BlockNumberDescNullsLast = 'blockNumber_DESC_NULLS_LAST', + ClaimedAsc = 'claimed_ASC', + ClaimedAscNullsFirst = 'claimed_ASC_NULLS_FIRST', + ClaimedAscNullsLast = 'claimed_ASC_NULLS_LAST', + ClaimedDesc = 'claimed_DESC', + ClaimedDescNullsFirst = 'claimed_DESC_NULLS_FIRST', + ClaimedDescNullsLast = 'claimed_DESC_NULLS_LAST', + IdAsc = 'id_ASC', + IdAscNullsFirst = 'id_ASC_NULLS_FIRST', + IdAscNullsLast = 'id_ASC_NULLS_LAST', + IdDesc = 'id_DESC', + IdDescNullsFirst = 'id_DESC_NULLS_FIRST', + IdDescNullsLast = 'id_DESC_NULLS_LAST', + QueuedAsc = 'queued_ASC', + QueuedAscNullsFirst = 'queued_ASC_NULLS_FIRST', + QueuedAscNullsLast = 'queued_ASC_NULLS_LAST', + QueuedDesc = 'queued_DESC', + QueuedDescNullsFirst = 'queued_DESC_NULLS_FIRST', + QueuedDescNullsLast = 'queued_DESC_NULLS_LAST', + RequestIdAsc = 'requestId_ASC', + RequestIdAscNullsFirst = 'requestId_ASC_NULLS_FIRST', + RequestIdAscNullsLast = 'requestId_ASC_NULLS_LAST', + RequestIdDesc = 'requestId_DESC', + RequestIdDescNullsFirst = 'requestId_DESC_NULLS_FIRST', + RequestIdDescNullsLast = 'requestId_DESC_NULLS_LAST', + TimestampAsc = 'timestamp_ASC', + TimestampAscNullsFirst = 'timestamp_ASC_NULLS_FIRST', + TimestampAscNullsLast = 'timestamp_ASC_NULLS_LAST', + TimestampDesc = 'timestamp_DESC', + TimestampDescNullsFirst = 'timestamp_DESC_NULLS_FIRST', + TimestampDescNullsLast = 'timestamp_DESC_NULLS_LAST', + WithdrawerAsc = 'withdrawer_ASC', + WithdrawerAscNullsFirst = 'withdrawer_ASC_NULLS_FIRST', + WithdrawerAscNullsLast = 'withdrawer_ASC_NULLS_LAST', + WithdrawerDesc = 'withdrawer_DESC', + WithdrawerDescNullsFirst = 'withdrawer_DESC_NULLS_FIRST', + WithdrawerDescNullsLast = 'withdrawer_DESC_NULLS_LAST' +} + +export type OethWithdrawalRequestWhereInput = { + AND?: InputMaybe>; + OR?: InputMaybe>; + amount_eq?: InputMaybe; + amount_gt?: InputMaybe; + amount_gte?: InputMaybe; + amount_in?: InputMaybe>; + amount_isNull?: InputMaybe; + amount_lt?: InputMaybe; + amount_lte?: InputMaybe; + amount_not_eq?: InputMaybe; + amount_not_in?: InputMaybe>; + blockNumber_eq?: InputMaybe; + blockNumber_gt?: InputMaybe; + blockNumber_gte?: InputMaybe; + blockNumber_in?: InputMaybe>; + blockNumber_isNull?: InputMaybe; + blockNumber_lt?: InputMaybe; + blockNumber_lte?: InputMaybe; + blockNumber_not_eq?: InputMaybe; + blockNumber_not_in?: InputMaybe>; + claimed_eq?: InputMaybe; + claimed_isNull?: InputMaybe; + claimed_not_eq?: InputMaybe; + id_contains?: InputMaybe; + id_containsInsensitive?: InputMaybe; + id_endsWith?: InputMaybe; + id_eq?: InputMaybe; + id_gt?: InputMaybe; + id_gte?: InputMaybe; + id_in?: InputMaybe>; + id_isNull?: InputMaybe; + id_lt?: InputMaybe; + id_lte?: InputMaybe; + id_not_contains?: InputMaybe; + id_not_containsInsensitive?: InputMaybe; + id_not_endsWith?: InputMaybe; + id_not_eq?: InputMaybe; + id_not_in?: InputMaybe>; + id_not_startsWith?: InputMaybe; + id_startsWith?: InputMaybe; + queued_eq?: InputMaybe; + queued_gt?: InputMaybe; + queued_gte?: InputMaybe; + queued_in?: InputMaybe>; + queued_isNull?: InputMaybe; + queued_lt?: InputMaybe; + queued_lte?: InputMaybe; + queued_not_eq?: InputMaybe; + queued_not_in?: InputMaybe>; + requestId_eq?: InputMaybe; + requestId_gt?: InputMaybe; + requestId_gte?: InputMaybe; + requestId_in?: InputMaybe>; + requestId_isNull?: InputMaybe; + requestId_lt?: InputMaybe; + requestId_lte?: InputMaybe; + requestId_not_eq?: InputMaybe; + requestId_not_in?: InputMaybe>; + timestamp_eq?: InputMaybe; + timestamp_gt?: InputMaybe; + timestamp_gte?: InputMaybe; + timestamp_in?: InputMaybe>; + timestamp_isNull?: InputMaybe; + timestamp_lt?: InputMaybe; + timestamp_lte?: InputMaybe; + timestamp_not_eq?: InputMaybe; + timestamp_not_in?: InputMaybe>; + withdrawer_contains?: InputMaybe; + withdrawer_containsInsensitive?: InputMaybe; + withdrawer_endsWith?: InputMaybe; + withdrawer_eq?: InputMaybe; + withdrawer_gt?: InputMaybe; + withdrawer_gte?: InputMaybe; + withdrawer_in?: InputMaybe>; + withdrawer_isNull?: InputMaybe; + withdrawer_lt?: InputMaybe; + withdrawer_lte?: InputMaybe; + withdrawer_not_contains?: InputMaybe; + withdrawer_not_containsInsensitive?: InputMaybe; + withdrawer_not_endsWith?: InputMaybe; + withdrawer_not_eq?: InputMaybe; + withdrawer_not_in?: InputMaybe>; + withdrawer_not_startsWith?: InputMaybe; + withdrawer_startsWith?: InputMaybe; +}; + +export type OethWithdrawalRequestsConnection = { + __typename?: 'OETHWithdrawalRequestsConnection'; + edges: Array; + pageInfo: PageInfo; + totalCount: Scalars['Int']['output']; +}; + export type OgnStatsResult = { __typename?: 'OGNStatsResult'; circulatingSupply: Scalars['Float']['output']; @@ -16370,6 +16533,11 @@ export type Query = { oethVaultByUniqueInput?: Maybe; oethVaults: Array; oethVaultsConnection: OethVaultsConnection; + oethWithdrawalRequestById?: Maybe; + /** @deprecated Use oethWithdrawalRequestById */ + oethWithdrawalRequestByUniqueInput?: Maybe; + oethWithdrawalRequests: Array; + oethWithdrawalRequestsConnection: OethWithdrawalRequestsConnection; ognStats: OgnStatsResult; ogvAddressById?: Maybe; /** @deprecated Use ogvAddressById */ @@ -18086,6 +18254,32 @@ export type QueryOethVaultsConnectionArgs = { }; +export type QueryOethWithdrawalRequestByIdArgs = { + id: Scalars['String']['input']; +}; + + +export type QueryOethWithdrawalRequestByUniqueInputArgs = { + where: WhereIdInput; +}; + + +export type QueryOethWithdrawalRequestsArgs = { + limit?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe>; + where?: InputMaybe; +}; + + +export type QueryOethWithdrawalRequestsConnectionArgs = { + after?: InputMaybe; + first?: InputMaybe; + orderBy: Array; + where?: InputMaybe; +}; + + export type QueryOgvAddressByIdArgs = { id: Scalars['String']['input']; }; diff --git a/libs/oeth/shared/src/generated/graphql.ts b/libs/oeth/shared/src/generated/graphql.ts index 2af37c450..129fedefe 100644 --- a/libs/oeth/shared/src/generated/graphql.ts +++ b/libs/oeth/shared/src/generated/graphql.ts @@ -9933,6 +9933,169 @@ export type OethVaultsConnection = { totalCount: Scalars['Int']['output']; }; +export type OethWithdrawalRequest = { + __typename?: 'OETHWithdrawalRequest'; + amount: Scalars['BigInt']['output']; + blockNumber: Scalars['Int']['output']; + claimed: Scalars['Boolean']['output']; + id: Scalars['String']['output']; + queued: Scalars['BigInt']['output']; + requestId: Scalars['BigInt']['output']; + timestamp: Scalars['DateTime']['output']; + withdrawer: Scalars['String']['output']; +}; + +export type OethWithdrawalRequestEdge = { + __typename?: 'OETHWithdrawalRequestEdge'; + cursor: Scalars['String']['output']; + node: OethWithdrawalRequest; +}; + +export enum OethWithdrawalRequestOrderByInput { + AmountAsc = 'amount_ASC', + AmountAscNullsFirst = 'amount_ASC_NULLS_FIRST', + AmountAscNullsLast = 'amount_ASC_NULLS_LAST', + AmountDesc = 'amount_DESC', + AmountDescNullsFirst = 'amount_DESC_NULLS_FIRST', + AmountDescNullsLast = 'amount_DESC_NULLS_LAST', + BlockNumberAsc = 'blockNumber_ASC', + BlockNumberAscNullsFirst = 'blockNumber_ASC_NULLS_FIRST', + BlockNumberAscNullsLast = 'blockNumber_ASC_NULLS_LAST', + BlockNumberDesc = 'blockNumber_DESC', + BlockNumberDescNullsFirst = 'blockNumber_DESC_NULLS_FIRST', + BlockNumberDescNullsLast = 'blockNumber_DESC_NULLS_LAST', + ClaimedAsc = 'claimed_ASC', + ClaimedAscNullsFirst = 'claimed_ASC_NULLS_FIRST', + ClaimedAscNullsLast = 'claimed_ASC_NULLS_LAST', + ClaimedDesc = 'claimed_DESC', + ClaimedDescNullsFirst = 'claimed_DESC_NULLS_FIRST', + ClaimedDescNullsLast = 'claimed_DESC_NULLS_LAST', + IdAsc = 'id_ASC', + IdAscNullsFirst = 'id_ASC_NULLS_FIRST', + IdAscNullsLast = 'id_ASC_NULLS_LAST', + IdDesc = 'id_DESC', + IdDescNullsFirst = 'id_DESC_NULLS_FIRST', + IdDescNullsLast = 'id_DESC_NULLS_LAST', + QueuedAsc = 'queued_ASC', + QueuedAscNullsFirst = 'queued_ASC_NULLS_FIRST', + QueuedAscNullsLast = 'queued_ASC_NULLS_LAST', + QueuedDesc = 'queued_DESC', + QueuedDescNullsFirst = 'queued_DESC_NULLS_FIRST', + QueuedDescNullsLast = 'queued_DESC_NULLS_LAST', + RequestIdAsc = 'requestId_ASC', + RequestIdAscNullsFirst = 'requestId_ASC_NULLS_FIRST', + RequestIdAscNullsLast = 'requestId_ASC_NULLS_LAST', + RequestIdDesc = 'requestId_DESC', + RequestIdDescNullsFirst = 'requestId_DESC_NULLS_FIRST', + RequestIdDescNullsLast = 'requestId_DESC_NULLS_LAST', + TimestampAsc = 'timestamp_ASC', + TimestampAscNullsFirst = 'timestamp_ASC_NULLS_FIRST', + TimestampAscNullsLast = 'timestamp_ASC_NULLS_LAST', + TimestampDesc = 'timestamp_DESC', + TimestampDescNullsFirst = 'timestamp_DESC_NULLS_FIRST', + TimestampDescNullsLast = 'timestamp_DESC_NULLS_LAST', + WithdrawerAsc = 'withdrawer_ASC', + WithdrawerAscNullsFirst = 'withdrawer_ASC_NULLS_FIRST', + WithdrawerAscNullsLast = 'withdrawer_ASC_NULLS_LAST', + WithdrawerDesc = 'withdrawer_DESC', + WithdrawerDescNullsFirst = 'withdrawer_DESC_NULLS_FIRST', + WithdrawerDescNullsLast = 'withdrawer_DESC_NULLS_LAST' +} + +export type OethWithdrawalRequestWhereInput = { + AND?: InputMaybe>; + OR?: InputMaybe>; + amount_eq?: InputMaybe; + amount_gt?: InputMaybe; + amount_gte?: InputMaybe; + amount_in?: InputMaybe>; + amount_isNull?: InputMaybe; + amount_lt?: InputMaybe; + amount_lte?: InputMaybe; + amount_not_eq?: InputMaybe; + amount_not_in?: InputMaybe>; + blockNumber_eq?: InputMaybe; + blockNumber_gt?: InputMaybe; + blockNumber_gte?: InputMaybe; + blockNumber_in?: InputMaybe>; + blockNumber_isNull?: InputMaybe; + blockNumber_lt?: InputMaybe; + blockNumber_lte?: InputMaybe; + blockNumber_not_eq?: InputMaybe; + blockNumber_not_in?: InputMaybe>; + claimed_eq?: InputMaybe; + claimed_isNull?: InputMaybe; + claimed_not_eq?: InputMaybe; + id_contains?: InputMaybe; + id_containsInsensitive?: InputMaybe; + id_endsWith?: InputMaybe; + id_eq?: InputMaybe; + id_gt?: InputMaybe; + id_gte?: InputMaybe; + id_in?: InputMaybe>; + id_isNull?: InputMaybe; + id_lt?: InputMaybe; + id_lte?: InputMaybe; + id_not_contains?: InputMaybe; + id_not_containsInsensitive?: InputMaybe; + id_not_endsWith?: InputMaybe; + id_not_eq?: InputMaybe; + id_not_in?: InputMaybe>; + id_not_startsWith?: InputMaybe; + id_startsWith?: InputMaybe; + queued_eq?: InputMaybe; + queued_gt?: InputMaybe; + queued_gte?: InputMaybe; + queued_in?: InputMaybe>; + queued_isNull?: InputMaybe; + queued_lt?: InputMaybe; + queued_lte?: InputMaybe; + queued_not_eq?: InputMaybe; + queued_not_in?: InputMaybe>; + requestId_eq?: InputMaybe; + requestId_gt?: InputMaybe; + requestId_gte?: InputMaybe; + requestId_in?: InputMaybe>; + requestId_isNull?: InputMaybe; + requestId_lt?: InputMaybe; + requestId_lte?: InputMaybe; + requestId_not_eq?: InputMaybe; + requestId_not_in?: InputMaybe>; + timestamp_eq?: InputMaybe; + timestamp_gt?: InputMaybe; + timestamp_gte?: InputMaybe; + timestamp_in?: InputMaybe>; + timestamp_isNull?: InputMaybe; + timestamp_lt?: InputMaybe; + timestamp_lte?: InputMaybe; + timestamp_not_eq?: InputMaybe; + timestamp_not_in?: InputMaybe>; + withdrawer_contains?: InputMaybe; + withdrawer_containsInsensitive?: InputMaybe; + withdrawer_endsWith?: InputMaybe; + withdrawer_eq?: InputMaybe; + withdrawer_gt?: InputMaybe; + withdrawer_gte?: InputMaybe; + withdrawer_in?: InputMaybe>; + withdrawer_isNull?: InputMaybe; + withdrawer_lt?: InputMaybe; + withdrawer_lte?: InputMaybe; + withdrawer_not_contains?: InputMaybe; + withdrawer_not_containsInsensitive?: InputMaybe; + withdrawer_not_endsWith?: InputMaybe; + withdrawer_not_eq?: InputMaybe; + withdrawer_not_in?: InputMaybe>; + withdrawer_not_startsWith?: InputMaybe; + withdrawer_startsWith?: InputMaybe; +}; + +export type OethWithdrawalRequestsConnection = { + __typename?: 'OETHWithdrawalRequestsConnection'; + edges: Array; + pageInfo: PageInfo; + totalCount: Scalars['Int']['output']; +}; + export type OgnStatsResult = { __typename?: 'OGNStatsResult'; circulatingSupply: Scalars['Float']['output']; @@ -16370,6 +16533,11 @@ export type Query = { oethVaultByUniqueInput?: Maybe; oethVaults: Array; oethVaultsConnection: OethVaultsConnection; + oethWithdrawalRequestById?: Maybe; + /** @deprecated Use oethWithdrawalRequestById */ + oethWithdrawalRequestByUniqueInput?: Maybe; + oethWithdrawalRequests: Array; + oethWithdrawalRequestsConnection: OethWithdrawalRequestsConnection; ognStats: OgnStatsResult; ogvAddressById?: Maybe; /** @deprecated Use ogvAddressById */ @@ -18086,6 +18254,32 @@ export type QueryOethVaultsConnectionArgs = { }; +export type QueryOethWithdrawalRequestByIdArgs = { + id: Scalars['String']['input']; +}; + + +export type QueryOethWithdrawalRequestByUniqueInputArgs = { + where: WhereIdInput; +}; + + +export type QueryOethWithdrawalRequestsArgs = { + limit?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe>; + where?: InputMaybe; +}; + + +export type QueryOethWithdrawalRequestsConnectionArgs = { + after?: InputMaybe; + first?: InputMaybe; + orderBy: Array; + where?: InputMaybe; +}; + + export type QueryOgvAddressByIdArgs = { id: Scalars['String']['input']; }; diff --git a/libs/ousd/shared/src/generated/graphql.ts b/libs/ousd/shared/src/generated/graphql.ts index 2af37c450..129fedefe 100644 --- a/libs/ousd/shared/src/generated/graphql.ts +++ b/libs/ousd/shared/src/generated/graphql.ts @@ -9933,6 +9933,169 @@ export type OethVaultsConnection = { totalCount: Scalars['Int']['output']; }; +export type OethWithdrawalRequest = { + __typename?: 'OETHWithdrawalRequest'; + amount: Scalars['BigInt']['output']; + blockNumber: Scalars['Int']['output']; + claimed: Scalars['Boolean']['output']; + id: Scalars['String']['output']; + queued: Scalars['BigInt']['output']; + requestId: Scalars['BigInt']['output']; + timestamp: Scalars['DateTime']['output']; + withdrawer: Scalars['String']['output']; +}; + +export type OethWithdrawalRequestEdge = { + __typename?: 'OETHWithdrawalRequestEdge'; + cursor: Scalars['String']['output']; + node: OethWithdrawalRequest; +}; + +export enum OethWithdrawalRequestOrderByInput { + AmountAsc = 'amount_ASC', + AmountAscNullsFirst = 'amount_ASC_NULLS_FIRST', + AmountAscNullsLast = 'amount_ASC_NULLS_LAST', + AmountDesc = 'amount_DESC', + AmountDescNullsFirst = 'amount_DESC_NULLS_FIRST', + AmountDescNullsLast = 'amount_DESC_NULLS_LAST', + BlockNumberAsc = 'blockNumber_ASC', + BlockNumberAscNullsFirst = 'blockNumber_ASC_NULLS_FIRST', + BlockNumberAscNullsLast = 'blockNumber_ASC_NULLS_LAST', + BlockNumberDesc = 'blockNumber_DESC', + BlockNumberDescNullsFirst = 'blockNumber_DESC_NULLS_FIRST', + BlockNumberDescNullsLast = 'blockNumber_DESC_NULLS_LAST', + ClaimedAsc = 'claimed_ASC', + ClaimedAscNullsFirst = 'claimed_ASC_NULLS_FIRST', + ClaimedAscNullsLast = 'claimed_ASC_NULLS_LAST', + ClaimedDesc = 'claimed_DESC', + ClaimedDescNullsFirst = 'claimed_DESC_NULLS_FIRST', + ClaimedDescNullsLast = 'claimed_DESC_NULLS_LAST', + IdAsc = 'id_ASC', + IdAscNullsFirst = 'id_ASC_NULLS_FIRST', + IdAscNullsLast = 'id_ASC_NULLS_LAST', + IdDesc = 'id_DESC', + IdDescNullsFirst = 'id_DESC_NULLS_FIRST', + IdDescNullsLast = 'id_DESC_NULLS_LAST', + QueuedAsc = 'queued_ASC', + QueuedAscNullsFirst = 'queued_ASC_NULLS_FIRST', + QueuedAscNullsLast = 'queued_ASC_NULLS_LAST', + QueuedDesc = 'queued_DESC', + QueuedDescNullsFirst = 'queued_DESC_NULLS_FIRST', + QueuedDescNullsLast = 'queued_DESC_NULLS_LAST', + RequestIdAsc = 'requestId_ASC', + RequestIdAscNullsFirst = 'requestId_ASC_NULLS_FIRST', + RequestIdAscNullsLast = 'requestId_ASC_NULLS_LAST', + RequestIdDesc = 'requestId_DESC', + RequestIdDescNullsFirst = 'requestId_DESC_NULLS_FIRST', + RequestIdDescNullsLast = 'requestId_DESC_NULLS_LAST', + TimestampAsc = 'timestamp_ASC', + TimestampAscNullsFirst = 'timestamp_ASC_NULLS_FIRST', + TimestampAscNullsLast = 'timestamp_ASC_NULLS_LAST', + TimestampDesc = 'timestamp_DESC', + TimestampDescNullsFirst = 'timestamp_DESC_NULLS_FIRST', + TimestampDescNullsLast = 'timestamp_DESC_NULLS_LAST', + WithdrawerAsc = 'withdrawer_ASC', + WithdrawerAscNullsFirst = 'withdrawer_ASC_NULLS_FIRST', + WithdrawerAscNullsLast = 'withdrawer_ASC_NULLS_LAST', + WithdrawerDesc = 'withdrawer_DESC', + WithdrawerDescNullsFirst = 'withdrawer_DESC_NULLS_FIRST', + WithdrawerDescNullsLast = 'withdrawer_DESC_NULLS_LAST' +} + +export type OethWithdrawalRequestWhereInput = { + AND?: InputMaybe>; + OR?: InputMaybe>; + amount_eq?: InputMaybe; + amount_gt?: InputMaybe; + amount_gte?: InputMaybe; + amount_in?: InputMaybe>; + amount_isNull?: InputMaybe; + amount_lt?: InputMaybe; + amount_lte?: InputMaybe; + amount_not_eq?: InputMaybe; + amount_not_in?: InputMaybe>; + blockNumber_eq?: InputMaybe; + blockNumber_gt?: InputMaybe; + blockNumber_gte?: InputMaybe; + blockNumber_in?: InputMaybe>; + blockNumber_isNull?: InputMaybe; + blockNumber_lt?: InputMaybe; + blockNumber_lte?: InputMaybe; + blockNumber_not_eq?: InputMaybe; + blockNumber_not_in?: InputMaybe>; + claimed_eq?: InputMaybe; + claimed_isNull?: InputMaybe; + claimed_not_eq?: InputMaybe; + id_contains?: InputMaybe; + id_containsInsensitive?: InputMaybe; + id_endsWith?: InputMaybe; + id_eq?: InputMaybe; + id_gt?: InputMaybe; + id_gte?: InputMaybe; + id_in?: InputMaybe>; + id_isNull?: InputMaybe; + id_lt?: InputMaybe; + id_lte?: InputMaybe; + id_not_contains?: InputMaybe; + id_not_containsInsensitive?: InputMaybe; + id_not_endsWith?: InputMaybe; + id_not_eq?: InputMaybe; + id_not_in?: InputMaybe>; + id_not_startsWith?: InputMaybe; + id_startsWith?: InputMaybe; + queued_eq?: InputMaybe; + queued_gt?: InputMaybe; + queued_gte?: InputMaybe; + queued_in?: InputMaybe>; + queued_isNull?: InputMaybe; + queued_lt?: InputMaybe; + queued_lte?: InputMaybe; + queued_not_eq?: InputMaybe; + queued_not_in?: InputMaybe>; + requestId_eq?: InputMaybe; + requestId_gt?: InputMaybe; + requestId_gte?: InputMaybe; + requestId_in?: InputMaybe>; + requestId_isNull?: InputMaybe; + requestId_lt?: InputMaybe; + requestId_lte?: InputMaybe; + requestId_not_eq?: InputMaybe; + requestId_not_in?: InputMaybe>; + timestamp_eq?: InputMaybe; + timestamp_gt?: InputMaybe; + timestamp_gte?: InputMaybe; + timestamp_in?: InputMaybe>; + timestamp_isNull?: InputMaybe; + timestamp_lt?: InputMaybe; + timestamp_lte?: InputMaybe; + timestamp_not_eq?: InputMaybe; + timestamp_not_in?: InputMaybe>; + withdrawer_contains?: InputMaybe; + withdrawer_containsInsensitive?: InputMaybe; + withdrawer_endsWith?: InputMaybe; + withdrawer_eq?: InputMaybe; + withdrawer_gt?: InputMaybe; + withdrawer_gte?: InputMaybe; + withdrawer_in?: InputMaybe>; + withdrawer_isNull?: InputMaybe; + withdrawer_lt?: InputMaybe; + withdrawer_lte?: InputMaybe; + withdrawer_not_contains?: InputMaybe; + withdrawer_not_containsInsensitive?: InputMaybe; + withdrawer_not_endsWith?: InputMaybe; + withdrawer_not_eq?: InputMaybe; + withdrawer_not_in?: InputMaybe>; + withdrawer_not_startsWith?: InputMaybe; + withdrawer_startsWith?: InputMaybe; +}; + +export type OethWithdrawalRequestsConnection = { + __typename?: 'OETHWithdrawalRequestsConnection'; + edges: Array; + pageInfo: PageInfo; + totalCount: Scalars['Int']['output']; +}; + export type OgnStatsResult = { __typename?: 'OGNStatsResult'; circulatingSupply: Scalars['Float']['output']; @@ -16370,6 +16533,11 @@ export type Query = { oethVaultByUniqueInput?: Maybe; oethVaults: Array; oethVaultsConnection: OethVaultsConnection; + oethWithdrawalRequestById?: Maybe; + /** @deprecated Use oethWithdrawalRequestById */ + oethWithdrawalRequestByUniqueInput?: Maybe; + oethWithdrawalRequests: Array; + oethWithdrawalRequestsConnection: OethWithdrawalRequestsConnection; ognStats: OgnStatsResult; ogvAddressById?: Maybe; /** @deprecated Use ogvAddressById */ @@ -18086,6 +18254,32 @@ export type QueryOethVaultsConnectionArgs = { }; +export type QueryOethWithdrawalRequestByIdArgs = { + id: Scalars['String']['input']; +}; + + +export type QueryOethWithdrawalRequestByUniqueInputArgs = { + where: WhereIdInput; +}; + + +export type QueryOethWithdrawalRequestsArgs = { + limit?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe>; + where?: InputMaybe; +}; + + +export type QueryOethWithdrawalRequestsConnectionArgs = { + after?: InputMaybe; + first?: InputMaybe; + orderBy: Array; + where?: InputMaybe; +}; + + export type QueryOgvAddressByIdArgs = { id: Scalars['String']['input']; }; From 0ab9fa24f4ea2f52df704bc01a6f1146123a79ec Mon Sep 17 00:00:00 2001 From: toniocodo Date: Wed, 10 Jul 2024 21:00:42 +0200 Subject: [PATCH 05/33] feat: add gas loading state --- libs/defi/oeth/src/redeem/components/Swapper.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/defi/oeth/src/redeem/components/Swapper.tsx b/libs/defi/oeth/src/redeem/components/Swapper.tsx index 369d440a0..9e14c8d3a 100644 --- a/libs/defi/oeth/src/redeem/components/Swapper.tsx +++ b/libs/defi/oeth/src/redeem/components/Swapper.tsx @@ -435,6 +435,7 @@ function SwapperWrapped({ 'Claiming your withdrawal will incur this estimated additional gas fee', })} value={`$${format(gasPrice?.gasCostUsd ?? from(0), 2)}`} + isLoading={isGasPriceLoading} direction="row" justifyContent="space-between" pt={1} From 84944bfd5d89468e191c8262ec5c93a42f9a2695 Mon Sep 17 00:00:00 2001 From: toniocodo Date: Wed, 10 Jul 2024 21:01:26 +0200 Subject: [PATCH 06/33] fix: route selection update --- .../redeem/components/RedeemActionCard.tsx | 20 ++----------------- 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/libs/defi/oeth/src/redeem/components/RedeemActionCard.tsx b/libs/defi/oeth/src/redeem/components/RedeemActionCard.tsx index 91e6d7e69..b27ce67f8 100644 --- a/libs/defi/oeth/src/redeem/components/RedeemActionCard.tsx +++ b/libs/defi/oeth/src/redeem/components/RedeemActionCard.tsx @@ -1,18 +1,13 @@ import { alpha, Card, Stack, SvgIcon, Typography } from '@mui/material'; import { ValueLabel } from '@origin/shared/components'; import { OETH } from '@origin/shared/icons'; -import { - routeEq, - useHandleSelectSwapRoute, - useIsSwapRouteAvailable, - useSwapState, -} from '@origin/shared/providers'; +import { routeEq, useSwapState } from '@origin/shared/providers'; import { format, from } from 'dnum'; import { useIntl } from 'react-intl'; import type { CardProps, TypographyProps } from '@mui/material'; import type { ValueLabelProps } from '@origin/shared/components'; -import type { EstimatedSwapRoute, SwapRoute } from '@origin/shared/providers'; +import type { SwapRoute } from '@origin/shared/providers'; import type { Meta, OethRedeemAction } from '../types'; @@ -37,20 +32,15 @@ export const RedeemActionCard = ({ swapActions, }, ] = useSwapState(); - const handleSelectSwapRoute = useHandleSelectSwapRoute(); const route = swapRoutes.find((r) => routeEq({ tokenIn, tokenOut, action }, r), ); - const { data: isRouteAvailable, isLoading: isRouteAvailableLoading } = - useIsSwapRouteAvailable(route); const estimatedRoute = estimatedSwapRoutes.find((r) => routeEq(r, route)); const isSelected = routeEq({ tokenIn, tokenOut, action }, selectedSwapRoute); const isEmptyValue = amountIn === 0n; const isComingSoon = (route as SwapRoute)?.meta?.comingSoon ?? false; const routeLabel = swapActions[action].routeLabel; - const isDisabled = - isComingSoon || (!isRouteAvailableLoading && !isRouteAvailable); return ( { - if (!isDisabled && amountIn > 0n) { - handleSelectSwapRoute(route as unknown as EstimatedSwapRoute); - } - }} > {isComingSoon && ( Date: Wed, 10 Jul 2024 22:27:50 +0200 Subject: [PATCH 07/33] style: fix spacing --- libs/defi/oeth/src/redeem/components/Swapper.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/libs/defi/oeth/src/redeem/components/Swapper.tsx b/libs/defi/oeth/src/redeem/components/Swapper.tsx index 9e14c8d3a..a01c8f494 100644 --- a/libs/defi/oeth/src/redeem/components/Swapper.tsx +++ b/libs/defi/oeth/src/redeem/components/Swapper.tsx @@ -439,7 +439,6 @@ function SwapperWrapped({ direction="row" justifyContent="space-between" pt={1} - pb={3} px={1} labelProps={{ variant: 'body3', From 024f34b79e3b2fddc5bb8f38a43a7a724b5a3a82 Mon Sep 17 00:00:00 2001 From: toniocodo Date: Thu, 11 Jul 2024 10:48:30 +0200 Subject: [PATCH 08/33] feat: add waiting in modal, add color to meta --- apps/defi/.env | 2 +- .../redeem/components/RedeemActionCard.tsx | 9 + .../oeth/src/redeem/components/Swapper.tsx | 305 +++++++++--------- .../components/WithdrawalRequestModal.tsx | 226 ++++++++++--- libs/defi/oeth/src/redeem/constants.ts | 1 + libs/defi/oeth/src/redeem/types.ts | 1 + .../icons/src/fa/regular/exclamation.svg | 1 + libs/shared/icons/src/fa/regular/index.tsx | 4 + 8 files changed, 348 insertions(+), 201 deletions(-) create mode 100644 libs/shared/icons/src/fa/regular/exclamation.svg diff --git a/apps/defi/.env b/apps/defi/.env index e6a37e392..aa8f0c724 100644 --- a/apps/defi/.env +++ b/apps/defi/.env @@ -1,6 +1,6 @@ # TODO remove after tenderly testing # Set this to any custom RPC to override public endpoint -VITE_CUSTOM_RPC="https://virtual.mainnet.rpc.tenderly.co/e6243bfa-8701-4c53-af2b-ba435081669a" +VITE_CUSTOM_RPC="https://virtual.mainnet.rpc.tenderly.co/4817f636-347f-492b-82f0-778d2dfd051a" # Wallet Connect v2 project id VITE_WALLET_CONNECT_PROJECT_ID= diff --git a/libs/defi/oeth/src/redeem/components/RedeemActionCard.tsx b/libs/defi/oeth/src/redeem/components/RedeemActionCard.tsx index b27ce67f8..c9dd6b5a3 100644 --- a/libs/defi/oeth/src/redeem/components/RedeemActionCard.tsx +++ b/libs/defi/oeth/src/redeem/components/RedeemActionCard.tsx @@ -2,6 +2,7 @@ import { alpha, Card, Stack, SvgIcon, Typography } from '@mui/material'; import { ValueLabel } from '@origin/shared/components'; import { OETH } from '@origin/shared/icons'; import { routeEq, useSwapState } from '@origin/shared/providers'; +import { isNilOrEmpty } from '@origin/shared/utils'; import { format, from } from 'dnum'; import { useIntl } from 'react-intl'; @@ -126,6 +127,14 @@ export const RedeemActionCard = ({ ) ) } + valueProps={{ + ...valueLabelProps.valueProps, + ...(estimatedRoute?.meta !== undefined && + 'waitTimeColor' in estimatedRoute.meta && + !isNilOrEmpty(estimatedRoute.meta.waitTimeColor) && { + color: estimatedRoute?.meta.waitTimeColor as string, + }), + }} isLoading={isSwapRoutesLoading} /> - } onError={onError}> - - - - - - {intl.formatMessage({ defaultMessage: 'Amount' })} - - - - {intl.formatMessage({ defaultMessage: 'Duration' })} - - - - - - - {intl.formatMessage({ defaultMessage: 'Receive amount' })} - - + + + + + {intl.formatMessage({ defaultMessage: 'Amount' })} + + + + {intl.formatMessage({ defaultMessage: 'Duration' })} + + + + + + + {intl.formatMessage({ defaultMessage: 'Receive amount' })} + + + + - - - {format([amountOut ?? 0n, tokenOut?.decimals ?? 18], { - digits: getFormatPrecision([ - amountOut ?? 0n, - tokenOut?.decimals ?? 18, - ]), - decimalsRounding: 'ROUND_DOWN', - })} - - - ${amountIn === 0n ? '0.00' : format(amountOutUsd, 2)} - - - - - - - 0n}> - - - - - - - - + - {isSwapRoutesLoading ? ( - - ) : isSwapWaitingForSignature ? ( - intl.formatMessage({ - defaultMessage: 'Waiting for signature', - }) - ) : isSwapLoading ? ( - intl.formatMessage({ - defaultMessage: 'Processing Transaction', - }) - ) : ( - swapButtonLabel - )} - - - - - + ${amountIn === 0n ? '0.00' : format(amountOutUsd, 2)} + + + + + + + 0n}> + + + + + + + + + {isSwapRoutesLoading ? ( + + ) : isSwapWaitingForSignature ? ( + intl.formatMessage({ + defaultMessage: 'Waiting for signature', + }) + ) : isSwapLoading ? ( + intl.formatMessage({ + defaultMessage: 'Processing Transaction', + }) + ) : ( + swapButtonLabel + )} + + + ); } diff --git a/libs/defi/oeth/src/redeem/components/WithdrawalRequestModal.tsx b/libs/defi/oeth/src/redeem/components/WithdrawalRequestModal.tsx index 69a8ae2eb..b872c8775 100644 --- a/libs/defi/oeth/src/redeem/components/WithdrawalRequestModal.tsx +++ b/libs/defi/oeth/src/redeem/components/WithdrawalRequestModal.tsx @@ -1,6 +1,10 @@ +import { useState } from 'react'; + import { + alpha, Box, Button, + CircularProgress, Dialog, DialogContent, DialogTitle, @@ -10,19 +14,29 @@ import { useMediaQuery, useTheme, } from '@mui/material'; -import { FaCheckRegular, FaXmarkRegular } from '@origin/shared/icons'; +import { + FaCheckRegular, + FaExclamationRegular, + FaXmarkRegular, +} from '@origin/shared/icons'; import { BlockExplorerLink } from '@origin/shared/providers'; -import { getFormatPrecision } from '@origin/shared/utils'; +import { getFormatPrecision, ZERO_ADDRESS } from '@origin/shared/utils'; +import { useIntervalEffect, usePrevious } from '@react-hookz/web'; import { format } from 'dnum'; import { useIntl } from 'react-intl'; +import { useAccount } from 'wagmi'; import { useViewSelect } from '../hooks'; +import { useWithdrawalRequestsQuery } from '../queries.generated'; import type { DialogProps } from '@mui/material'; import type { Token } from '@origin/shared/contracts'; import type { Dnum } from 'dnum'; import type { TransactionReceipt } from 'viem'; +const INTERVAL = 2000; // ms +const MAX_RETRY = 10; // 10 * 2s = 20s + export type WithdrawalRequestModalProps = { amountOut?: bigint; tokenIn?: Token; @@ -30,6 +44,8 @@ export type WithdrawalRequestModalProps = { txReceipt?: TransactionReceipt; } & DialogProps; +type Status = 'processing' | 'processed' | 'timeout'; + export const WithdrawalRequestModal = ({ amountOut, tokenIn, @@ -42,6 +58,36 @@ export const WithdrawalRequestModal = ({ const theme = useTheme(); const fullScreen = useMediaQuery(theme.breakpoints.down('md')); const { update } = useViewSelect(); + const { address } = useAccount(); + const [status, setStatus] = useState('processing'); + const [retries, setRetries] = useState(0); + const { data: count } = useWithdrawalRequestsQuery( + { address: address ?? ZERO_ADDRESS }, + { + enabled: !!address, + refetchInterval: status === 'processing' ? INTERVAL : undefined, + select: (data) => data?.oethWithdrawalRequests?.length ?? 0, + }, + ); + const prevCount = usePrevious(count); + + useIntervalEffect( + () => { + if (status === 'processing') { + setRetries((prev) => prev + 1); + if ( + count !== undefined && + prevCount !== undefined && + count > prevCount + ) { + setStatus('processed'); + } else if (retries > MAX_RETRY) { + setStatus('timeout'); + } + } + }, + status === 'processing' ? INTERVAL : undefined, + ); const handleClaimClick = () => { update('claim'); @@ -49,6 +95,135 @@ export const WithdrawalRequestModal = ({ }; const amt = [amountOut ?? 0n, tokenOut?.decimals ?? 18] as Dnum; + const icon = { + processing: ( + + alpha(theme.palette.primary.main, 0.3), + }} + size={85} + thickness={4.4} + value={100} + /> + + + ), + processed: ( + + + + ), + timeout: ( + + + + ), + }[status]; + const label = { + processed: { + title: intl.formatMessage({ + defaultMessage: 'Withdrawal request successfully sent', + }), + subtitle: intl.formatMessage( + { + defaultMessage: + 'Your request to withdraw {amountOut} {symbolOut} from {symbolIn} has been sent. Check the Claim tab to view your withdrawal requests.', + }, + { + amountOut: format(amt, getFormatPrecision(amt)), + symbolIn: tokenIn?.symbol ?? '', + symbolOut: tokenOut?.symbol ?? '', + }, + ), + }, + timeout: { + title: intl.formatMessage({ + defaultMessage: 'Withdrawal request is taking a long time to process', + }), + subtitle: intl.formatMessage({ + defaultMessage: + 'Try to refresh the page and go to the Claim tab to see your withdrawal request', + }), + }, + processing: { + title: intl.formatMessage({ + defaultMessage: 'Your withdrawal is being processed', + }), + subtitle: intl.formatMessage({ + defaultMessage: 'This operation can take a few seconds to complete', + }), + }, + }[status]; + const button = { + timeout: ( + + ), + processed: ( + + ), + processing: ( + + ), + }[status]; return ( @@ -63,55 +238,22 @@ export const WithdrawalRequestModal = ({ - - - + {icon} - {intl.formatMessage({ - defaultMessage: 'Withdrawal request successfully sent', - })} + {label.title} - {intl.formatMessage( - { - defaultMessage: - 'Your request to withdraw {amountOut} {symbolOut} from {symbolIn} has been sent. Check the Claim tab to view your withdrawal requests.', - }, - { - amountOut: format(amt, getFormatPrecision(amt)), - symbolIn: tokenIn?.symbol ?? '', - symbolOut: tokenOut?.symbol ?? '', - }, - )} + {label.subtitle} - - {txReceipt && } + {button} + {txReceipt && ( + + )} diff --git a/libs/defi/oeth/src/redeem/constants.ts b/libs/defi/oeth/src/redeem/constants.ts index 4e42f289c..5e040d231 100644 --- a/libs/defi/oeth/src/redeem/constants.ts +++ b/libs/defi/oeth/src/redeem/constants.ts @@ -36,6 +36,7 @@ export const redeemRoutes: SwapRoute[] = [ meta: { icon: OETH, waitTime: defineMessage({ defaultMessage: '~a few days' }), + waitTimeColor: 'warning.main', }, }, ]; diff --git a/libs/defi/oeth/src/redeem/types.ts b/libs/defi/oeth/src/redeem/types.ts index 214ed0f8f..683207e30 100644 --- a/libs/defi/oeth/src/redeem/types.ts +++ b/libs/defi/oeth/src/redeem/types.ts @@ -5,6 +5,7 @@ import type { MessageDescriptor } from 'react-intl'; export type Meta = { icon?: ComponentType; waitTime?: MessageDescriptor; + waitTimeColor?: string; comingSoon?: boolean; }; diff --git a/libs/shared/icons/src/fa/regular/exclamation.svg b/libs/shared/icons/src/fa/regular/exclamation.svg new file mode 100644 index 000000000..d62f49e3c --- /dev/null +++ b/libs/shared/icons/src/fa/regular/exclamation.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/libs/shared/icons/src/fa/regular/index.tsx b/libs/shared/icons/src/fa/regular/index.tsx index b72916187..93e9a8d96 100644 --- a/libs/shared/icons/src/fa/regular/index.tsx +++ b/libs/shared/icons/src/fa/regular/index.tsx @@ -37,6 +37,7 @@ import CoinsSvg from './coins.svg?react'; import CommentsSvg from './comments.svg?react'; import CopySvg from './copy.svg?react'; import EllipsisVerticalSvg from './ellipsis-vertical.svg?react'; +import ExclamationSvg from './exclamation.svg?react'; import FileLinesSvg from './file-lines.svg?react'; import FilterSvg from './filter.svg?react'; import GavelSvg from './gavel.svg?react'; @@ -321,6 +322,9 @@ export const FaEllipsisVerticalRegular = (props: SvgIconProps) => ( inheritViewBox /> ); +export const FaExclamationRegular = (props: SvgIconProps) => ( + +); export const FaFileLinesRegular = (props: SvgIconProps) => ( Date: Thu, 11 Jul 2024 12:18:31 +0200 Subject: [PATCH 09/33] feat: add 30 min delay for claiming withdrawal requests --- libs/defi/oeth/src/redeem/constants.ts | 2 +- libs/defi/oeth/src/redeem/hooks.ts | 33 +++++++++++++++++++------- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/libs/defi/oeth/src/redeem/constants.ts b/libs/defi/oeth/src/redeem/constants.ts index 5e040d231..45309f004 100644 --- a/libs/defi/oeth/src/redeem/constants.ts +++ b/libs/defi/oeth/src/redeem/constants.ts @@ -35,7 +35,7 @@ export const redeemRoutes: SwapRoute[] = [ action: 'redeem-vault-async', meta: { icon: OETH, - waitTime: defineMessage({ defaultMessage: '~a few days' }), + waitTime: defineMessage({ defaultMessage: '~30 min - few days' }), waitTimeColor: 'warning.main', }, }, diff --git a/libs/defi/oeth/src/redeem/hooks.ts b/libs/defi/oeth/src/redeem/hooks.ts index c2bc99552..a122f2243 100644 --- a/libs/defi/oeth/src/redeem/hooks.ts +++ b/libs/defi/oeth/src/redeem/hooks.ts @@ -3,7 +3,8 @@ import { useMemo } from 'react'; import { contracts } from '@origin/shared/contracts'; import { isFulfilled, ZERO_ADDRESS } from '@origin/shared/utils'; import { useQuery, useQueryClient } from '@tanstack/react-query'; -import { readContract } from '@wagmi/core'; +import { getBlock, readContract } from '@wagmi/core'; +import { addMinutes, fromUnixTime, isAfter } from 'date-fns'; import { useSearchParams } from 'react-router-dom'; import { useAccount, useConfig } from 'wagmi'; @@ -67,20 +68,34 @@ export const useWithdrawalRequests = ( address: address ?? ZERO_ADDRESS, }), }), + getBlock(config, { + blockTag: 'finalized', + chainId: contracts.mainnet.OETHVault.chainId, + }), ]); const queueData = isFulfilled(res[0]) ? res[0].value : null; const requests = isFulfilled(res[1]) ? res[1].value?.oethWithdrawalRequests ?? [] : []; + const block = isFulfilled(res[2]) ? res[2].value : null; + + return requests.map((r) => { + const claimable = + !r.claimed && + BigInt(r.queued) <= BigInt(queueData?.claimable ?? 0) && + isAfter( + new Date(r.timestamp), + addMinutes(fromUnixTime(Number(block?.timestamp ?? 0)), 30), + ); - return requests.map((r) => ({ - ...r, - requestId: BigInt(r.requestId), - amount: BigInt(r.amount), - queued: BigInt(r.queued), - claimable: - !r.claimed && BigInt(r.queued) <= BigInt(queueData?.claimable ?? 0), - })); + return { + ...r, + requestId: BigInt(r.requestId), + amount: BigInt(r.amount), + queued: BigInt(r.queued), + claimable, + }; + }); }, }); }; From 031439516f57731558192598a43f748391e28c35 Mon Sep 17 00:00:00 2001 From: toniocodo Date: Thu, 11 Jul 2024 15:49:46 +0200 Subject: [PATCH 10/33] style: update fontweight and variant --- apps/defi/.env | 2 +- libs/defi/oeth/src/redeem/components/ClaimHeader.tsx | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/defi/.env b/apps/defi/.env index aa8f0c724..e6a37e392 100644 --- a/apps/defi/.env +++ b/apps/defi/.env @@ -1,6 +1,6 @@ # TODO remove after tenderly testing # Set this to any custom RPC to override public endpoint -VITE_CUSTOM_RPC="https://virtual.mainnet.rpc.tenderly.co/4817f636-347f-492b-82f0-778d2dfd051a" +VITE_CUSTOM_RPC="https://virtual.mainnet.rpc.tenderly.co/e6243bfa-8701-4c53-af2b-ba435081669a" # Wallet Connect v2 project id VITE_WALLET_CONNECT_PROJECT_ID= diff --git a/libs/defi/oeth/src/redeem/components/ClaimHeader.tsx b/libs/defi/oeth/src/redeem/components/ClaimHeader.tsx index 376a3a3d4..ccaa02c21 100644 --- a/libs/defi/oeth/src/redeem/components/ClaimHeader.tsx +++ b/libs/defi/oeth/src/redeem/components/ClaimHeader.tsx @@ -128,7 +128,9 @@ const IconChip = ({ claimable, amount, ...rest }: IconChipProps) => { }} > {claimable ? : } - {amount} + + {amount} + ); }; From 65d48cbac94dbe3930bdd70ffc64cac6abe3970b Mon Sep 17 00:00:00 2001 From: toniocodo Date: Thu, 11 Jul 2024 15:51:55 +0200 Subject: [PATCH 11/33] style: increase action link spacing --- libs/defi/oeth/src/redeem/components/WithdrawalRequestModal.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/defi/oeth/src/redeem/components/WithdrawalRequestModal.tsx b/libs/defi/oeth/src/redeem/components/WithdrawalRequestModal.tsx index b872c8775..9ecd19fa1 100644 --- a/libs/defi/oeth/src/redeem/components/WithdrawalRequestModal.tsx +++ b/libs/defi/oeth/src/redeem/components/WithdrawalRequestModal.tsx @@ -252,7 +252,7 @@ export const WithdrawalRequestModal = ({ {button} {txReceipt && ( - + )} From 05257836785835ad33fcb2b11c4e559f106cdabf Mon Sep 17 00:00:00 2001 From: toniocodo Date: Thu, 11 Jul 2024 16:44:51 +0200 Subject: [PATCH 12/33] style: update label text color --- .../oeth/src/redeem/components/WithdrawalRequestModal.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libs/defi/oeth/src/redeem/components/WithdrawalRequestModal.tsx b/libs/defi/oeth/src/redeem/components/WithdrawalRequestModal.tsx index 9ecd19fa1..d98b677db 100644 --- a/libs/defi/oeth/src/redeem/components/WithdrawalRequestModal.tsx +++ b/libs/defi/oeth/src/redeem/components/WithdrawalRequestModal.tsx @@ -247,7 +247,12 @@ export const WithdrawalRequestModal = ({ > {label.title} - + {label.subtitle} {button} From 4bce5efaedcea2985ee00ed5d53b059fde2ec04e Mon Sep 17 00:00:00 2001 From: toniocodo Date: Thu, 11 Jul 2024 19:44:52 +0200 Subject: [PATCH 13/33] feat: add split gas price --- .../oeth/src/redeem/components/Swapper.tsx | 51 ++++++++++++++++--- 1 file changed, 43 insertions(+), 8 deletions(-) diff --git a/libs/defi/oeth/src/redeem/components/Swapper.tsx b/libs/defi/oeth/src/redeem/components/Swapper.tsx index c29f439b3..9e4d328ea 100644 --- a/libs/defi/oeth/src/redeem/components/Swapper.tsx +++ b/libs/defi/oeth/src/redeem/components/Swapper.tsx @@ -19,7 +19,11 @@ import { usePushActivity, useUpdateActivity, } from '@origin/defi/shared'; -import { LoadingLabel, ValueLabel } from '@origin/shared/components'; +import { + InfoTooltipLabel, + LoadingLabel, + ValueLabel, +} from '@origin/shared/components'; import { ConnectedButton, getTokenPriceKey, @@ -50,7 +54,11 @@ import { WithdrawalRequestModal } from './WithdrawalRequestModal'; import type { StackProps } from '@mui/material'; import type { Activity } from '@origin/defi/shared'; -import type { SwapState } from '@origin/shared/providers'; +import type { + EstimatedSwapRoute, + GasPrice, + SwapState, +} from '@origin/shared/providers'; import type { Dnum } from 'dnum'; import type { WithdrawalRequestModalProps } from './WithdrawalRequestModal'; @@ -260,7 +268,6 @@ export const Swapper = ({ function SwapperWrapped({ onError, - ...rest }: Omit) { const intl = useIntl(); const { isConnected } = useAccount(); @@ -421,11 +428,9 @@ function SwapperWrapped({ label={intl.formatMessage({ defaultMessage: 'Approximate gas cost:', })} - labelInfoTooltip={intl.formatMessage({ - defaultMessage: - 'Claiming your withdrawal will incur this estimated additional gas fee', - })} - value={`$${format(gasPrice?.gasCostUsd ?? from(0), 2)}`} + value={ + + } isLoading={isGasPriceLoading} direction="row" justifyContent="space-between" @@ -487,3 +492,33 @@ function SwapperWrapped({ ); } + +type GasPriceLabelProps = { + route?: EstimatedSwapRoute | null; + gasPrice?: GasPrice; +}; + +const GasPriceLabel = ({ route, gasPrice, ...rest }: GasPriceLabelProps) => { + const intl = useIntl(); + + if (!gasPrice || !route || isNilOrEmpty(gasPrice?.gasCostUsd)) { + return `$0.00`; + } + + if (route.action !== 'redeem-vault-async') { + return `$${format(gasPrice?.gasCostUsd ?? from(0), 2)}`; + } + + const req = mul(gasPrice.gasCostUsd, 0.6); + const claim = mul(gasPrice.gasCostUsd, 0.4); + + return ( + {`~$${format(req, 2)} + ~$${format(claim, 2)}`} + ); +}; From f84b1d324564421d38ac8500bd96d2b777a0650c Mon Sep 17 00:00:00 2001 From: toniocodo Date: Thu, 11 Jul 2024 22:44:52 +0200 Subject: [PATCH 14/33] feat: add tx hash for redeem requests --- .../oeth/src/redeem/components/ClaimForm.tsx | 20 ++++++++++++++-- .../defi/oeth/src/redeem/queries.generated.ts | 3 ++- libs/defi/oeth/src/redeem/queries.graphql | 1 + libs/defi/oeth/src/redeem/types.ts | 1 + libs/defi/shared/src/generated/graphql.ts | 24 +++++++++++++++++++ .../shared/src/generated/graphql.ts | 24 +++++++++++++++++++ libs/oeth/shared/src/generated/graphql.ts | 24 +++++++++++++++++++ libs/ousd/shared/src/generated/graphql.ts | 24 +++++++++++++++++++ 8 files changed, 118 insertions(+), 3 deletions(-) diff --git a/libs/defi/oeth/src/redeem/components/ClaimForm.tsx b/libs/defi/oeth/src/redeem/components/ClaimForm.tsx index f3a94d36f..a6664ac9e 100644 --- a/libs/defi/oeth/src/redeem/components/ClaimForm.tsx +++ b/libs/defi/oeth/src/redeem/components/ClaimForm.tsx @@ -1,6 +1,7 @@ import { useMemo, useState } from 'react'; import { + Button, Checkbox, CircularProgress, Collapse, @@ -12,7 +13,11 @@ import { import { SectionCard, useTxButton } from '@origin/defi/shared'; import { ValueLabel } from '@origin/shared/components'; import { contracts, tokens } from '@origin/shared/contracts'; -import { FaCircleCheckRegular, FaClockRegular } from '@origin/shared/icons'; +import { + FaArrowUpRightRegular, + FaCircleCheckRegular, + FaClockRegular, +} from '@origin/shared/icons'; import { TxButton } from '@origin/shared/providers'; import { getFormatPrecision, @@ -201,7 +206,18 @@ const ClaimRow = ({ request, selected, onSelect, ...rest }: ClaimRowProps) => { disabled={!request.claimable} disableTypography /> - + + + + ); }; diff --git a/libs/defi/oeth/src/redeem/queries.generated.ts b/libs/defi/oeth/src/redeem/queries.generated.ts index 2f06336c3..aaf6feb94 100644 --- a/libs/defi/oeth/src/redeem/queries.generated.ts +++ b/libs/defi/oeth/src/redeem/queries.generated.ts @@ -7,7 +7,7 @@ export type WithdrawalRequestsQueryVariables = Types.Exact<{ }>; -export type WithdrawalRequestsQuery = { __typename?: 'Query', oethWithdrawalRequests: Array<{ __typename?: 'OETHWithdrawalRequest', id: string, requestId: string, timestamp: string, amount: string, queued: string, claimed: boolean, blockNumber: number }> }; +export type WithdrawalRequestsQuery = { __typename?: 'Query', oethWithdrawalRequests: Array<{ __typename?: 'OETHWithdrawalRequest', id: string, requestId: string, timestamp: string, amount: string, queued: string, claimed: boolean, blockNumber: number, txHash: string }> }; @@ -22,6 +22,7 @@ export const WithdrawalRequestsDocument = ` claimed blockNumber requestId + txHash } } `; diff --git a/libs/defi/oeth/src/redeem/queries.graphql b/libs/defi/oeth/src/redeem/queries.graphql index 62f59ac39..0d9ed4d97 100644 --- a/libs/defi/oeth/src/redeem/queries.graphql +++ b/libs/defi/oeth/src/redeem/queries.graphql @@ -8,5 +8,6 @@ query WithdrawalRequests($address: String!) { claimed blockNumber requestId + txHash } } diff --git a/libs/defi/oeth/src/redeem/types.ts b/libs/defi/oeth/src/redeem/types.ts index 683207e30..ee1dca6db 100644 --- a/libs/defi/oeth/src/redeem/types.ts +++ b/libs/defi/oeth/src/redeem/types.ts @@ -24,4 +24,5 @@ export type WithdrawalRequest = { claimed: boolean; blockNumber: number; claimable: boolean; + txHash: string; }; diff --git a/libs/defi/shared/src/generated/graphql.ts b/libs/defi/shared/src/generated/graphql.ts index 129fedefe..aaba0fa27 100644 --- a/libs/defi/shared/src/generated/graphql.ts +++ b/libs/defi/shared/src/generated/graphql.ts @@ -9942,6 +9942,7 @@ export type OethWithdrawalRequest = { queued: Scalars['BigInt']['output']; requestId: Scalars['BigInt']['output']; timestamp: Scalars['DateTime']['output']; + txHash: Scalars['String']['output']; withdrawer: Scalars['String']['output']; }; @@ -9994,6 +9995,12 @@ export enum OethWithdrawalRequestOrderByInput { TimestampDesc = 'timestamp_DESC', TimestampDescNullsFirst = 'timestamp_DESC_NULLS_FIRST', TimestampDescNullsLast = 'timestamp_DESC_NULLS_LAST', + TxHashAsc = 'txHash_ASC', + TxHashAscNullsFirst = 'txHash_ASC_NULLS_FIRST', + TxHashAscNullsLast = 'txHash_ASC_NULLS_LAST', + TxHashDesc = 'txHash_DESC', + TxHashDescNullsFirst = 'txHash_DESC_NULLS_FIRST', + TxHashDescNullsLast = 'txHash_DESC_NULLS_LAST', WithdrawerAsc = 'withdrawer_ASC', WithdrawerAscNullsFirst = 'withdrawer_ASC_NULLS_FIRST', WithdrawerAscNullsLast = 'withdrawer_ASC_NULLS_LAST', @@ -10070,6 +10077,23 @@ export type OethWithdrawalRequestWhereInput = { timestamp_lte?: InputMaybe; timestamp_not_eq?: InputMaybe; timestamp_not_in?: InputMaybe>; + txHash_contains?: InputMaybe; + txHash_containsInsensitive?: InputMaybe; + txHash_endsWith?: InputMaybe; + txHash_eq?: InputMaybe; + txHash_gt?: InputMaybe; + txHash_gte?: InputMaybe; + txHash_in?: InputMaybe>; + txHash_isNull?: InputMaybe; + txHash_lt?: InputMaybe; + txHash_lte?: InputMaybe; + txHash_not_contains?: InputMaybe; + txHash_not_containsInsensitive?: InputMaybe; + txHash_not_endsWith?: InputMaybe; + txHash_not_eq?: InputMaybe; + txHash_not_in?: InputMaybe>; + txHash_not_startsWith?: InputMaybe; + txHash_startsWith?: InputMaybe; withdrawer_contains?: InputMaybe; withdrawer_containsInsensitive?: InputMaybe; withdrawer_endsWith?: InputMaybe; diff --git a/libs/governance/shared/src/generated/graphql.ts b/libs/governance/shared/src/generated/graphql.ts index 129fedefe..aaba0fa27 100644 --- a/libs/governance/shared/src/generated/graphql.ts +++ b/libs/governance/shared/src/generated/graphql.ts @@ -9942,6 +9942,7 @@ export type OethWithdrawalRequest = { queued: Scalars['BigInt']['output']; requestId: Scalars['BigInt']['output']; timestamp: Scalars['DateTime']['output']; + txHash: Scalars['String']['output']; withdrawer: Scalars['String']['output']; }; @@ -9994,6 +9995,12 @@ export enum OethWithdrawalRequestOrderByInput { TimestampDesc = 'timestamp_DESC', TimestampDescNullsFirst = 'timestamp_DESC_NULLS_FIRST', TimestampDescNullsLast = 'timestamp_DESC_NULLS_LAST', + TxHashAsc = 'txHash_ASC', + TxHashAscNullsFirst = 'txHash_ASC_NULLS_FIRST', + TxHashAscNullsLast = 'txHash_ASC_NULLS_LAST', + TxHashDesc = 'txHash_DESC', + TxHashDescNullsFirst = 'txHash_DESC_NULLS_FIRST', + TxHashDescNullsLast = 'txHash_DESC_NULLS_LAST', WithdrawerAsc = 'withdrawer_ASC', WithdrawerAscNullsFirst = 'withdrawer_ASC_NULLS_FIRST', WithdrawerAscNullsLast = 'withdrawer_ASC_NULLS_LAST', @@ -10070,6 +10077,23 @@ export type OethWithdrawalRequestWhereInput = { timestamp_lte?: InputMaybe; timestamp_not_eq?: InputMaybe; timestamp_not_in?: InputMaybe>; + txHash_contains?: InputMaybe; + txHash_containsInsensitive?: InputMaybe; + txHash_endsWith?: InputMaybe; + txHash_eq?: InputMaybe; + txHash_gt?: InputMaybe; + txHash_gte?: InputMaybe; + txHash_in?: InputMaybe>; + txHash_isNull?: InputMaybe; + txHash_lt?: InputMaybe; + txHash_lte?: InputMaybe; + txHash_not_contains?: InputMaybe; + txHash_not_containsInsensitive?: InputMaybe; + txHash_not_endsWith?: InputMaybe; + txHash_not_eq?: InputMaybe; + txHash_not_in?: InputMaybe>; + txHash_not_startsWith?: InputMaybe; + txHash_startsWith?: InputMaybe; withdrawer_contains?: InputMaybe; withdrawer_containsInsensitive?: InputMaybe; withdrawer_endsWith?: InputMaybe; diff --git a/libs/oeth/shared/src/generated/graphql.ts b/libs/oeth/shared/src/generated/graphql.ts index 129fedefe..aaba0fa27 100644 --- a/libs/oeth/shared/src/generated/graphql.ts +++ b/libs/oeth/shared/src/generated/graphql.ts @@ -9942,6 +9942,7 @@ export type OethWithdrawalRequest = { queued: Scalars['BigInt']['output']; requestId: Scalars['BigInt']['output']; timestamp: Scalars['DateTime']['output']; + txHash: Scalars['String']['output']; withdrawer: Scalars['String']['output']; }; @@ -9994,6 +9995,12 @@ export enum OethWithdrawalRequestOrderByInput { TimestampDesc = 'timestamp_DESC', TimestampDescNullsFirst = 'timestamp_DESC_NULLS_FIRST', TimestampDescNullsLast = 'timestamp_DESC_NULLS_LAST', + TxHashAsc = 'txHash_ASC', + TxHashAscNullsFirst = 'txHash_ASC_NULLS_FIRST', + TxHashAscNullsLast = 'txHash_ASC_NULLS_LAST', + TxHashDesc = 'txHash_DESC', + TxHashDescNullsFirst = 'txHash_DESC_NULLS_FIRST', + TxHashDescNullsLast = 'txHash_DESC_NULLS_LAST', WithdrawerAsc = 'withdrawer_ASC', WithdrawerAscNullsFirst = 'withdrawer_ASC_NULLS_FIRST', WithdrawerAscNullsLast = 'withdrawer_ASC_NULLS_LAST', @@ -10070,6 +10077,23 @@ export type OethWithdrawalRequestWhereInput = { timestamp_lte?: InputMaybe; timestamp_not_eq?: InputMaybe; timestamp_not_in?: InputMaybe>; + txHash_contains?: InputMaybe; + txHash_containsInsensitive?: InputMaybe; + txHash_endsWith?: InputMaybe; + txHash_eq?: InputMaybe; + txHash_gt?: InputMaybe; + txHash_gte?: InputMaybe; + txHash_in?: InputMaybe>; + txHash_isNull?: InputMaybe; + txHash_lt?: InputMaybe; + txHash_lte?: InputMaybe; + txHash_not_contains?: InputMaybe; + txHash_not_containsInsensitive?: InputMaybe; + txHash_not_endsWith?: InputMaybe; + txHash_not_eq?: InputMaybe; + txHash_not_in?: InputMaybe>; + txHash_not_startsWith?: InputMaybe; + txHash_startsWith?: InputMaybe; withdrawer_contains?: InputMaybe; withdrawer_containsInsensitive?: InputMaybe; withdrawer_endsWith?: InputMaybe; diff --git a/libs/ousd/shared/src/generated/graphql.ts b/libs/ousd/shared/src/generated/graphql.ts index 129fedefe..aaba0fa27 100644 --- a/libs/ousd/shared/src/generated/graphql.ts +++ b/libs/ousd/shared/src/generated/graphql.ts @@ -9942,6 +9942,7 @@ export type OethWithdrawalRequest = { queued: Scalars['BigInt']['output']; requestId: Scalars['BigInt']['output']; timestamp: Scalars['DateTime']['output']; + txHash: Scalars['String']['output']; withdrawer: Scalars['String']['output']; }; @@ -9994,6 +9995,12 @@ export enum OethWithdrawalRequestOrderByInput { TimestampDesc = 'timestamp_DESC', TimestampDescNullsFirst = 'timestamp_DESC_NULLS_FIRST', TimestampDescNullsLast = 'timestamp_DESC_NULLS_LAST', + TxHashAsc = 'txHash_ASC', + TxHashAscNullsFirst = 'txHash_ASC_NULLS_FIRST', + TxHashAscNullsLast = 'txHash_ASC_NULLS_LAST', + TxHashDesc = 'txHash_DESC', + TxHashDescNullsFirst = 'txHash_DESC_NULLS_FIRST', + TxHashDescNullsLast = 'txHash_DESC_NULLS_LAST', WithdrawerAsc = 'withdrawer_ASC', WithdrawerAscNullsFirst = 'withdrawer_ASC_NULLS_FIRST', WithdrawerAscNullsLast = 'withdrawer_ASC_NULLS_LAST', @@ -10070,6 +10077,23 @@ export type OethWithdrawalRequestWhereInput = { timestamp_lte?: InputMaybe; timestamp_not_eq?: InputMaybe; timestamp_not_in?: InputMaybe>; + txHash_contains?: InputMaybe; + txHash_containsInsensitive?: InputMaybe; + txHash_endsWith?: InputMaybe; + txHash_eq?: InputMaybe; + txHash_gt?: InputMaybe; + txHash_gte?: InputMaybe; + txHash_in?: InputMaybe>; + txHash_isNull?: InputMaybe; + txHash_lt?: InputMaybe; + txHash_lte?: InputMaybe; + txHash_not_contains?: InputMaybe; + txHash_not_containsInsensitive?: InputMaybe; + txHash_not_endsWith?: InputMaybe; + txHash_not_eq?: InputMaybe; + txHash_not_in?: InputMaybe>; + txHash_not_startsWith?: InputMaybe; + txHash_startsWith?: InputMaybe; withdrawer_contains?: InputMaybe; withdrawer_containsInsensitive?: InputMaybe; withdrawer_endsWith?: InputMaybe; From 3fe45abec98fd40a3a367b6f2e4de2b320224798 Mon Sep 17 00:00:00 2001 From: toniocodo Date: Thu, 11 Jul 2024 22:45:14 +0200 Subject: [PATCH 15/33] chore: use withdrawal vnet --- apps/defi/.env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/defi/.env b/apps/defi/.env index e6a37e392..aa8f0c724 100644 --- a/apps/defi/.env +++ b/apps/defi/.env @@ -1,6 +1,6 @@ # TODO remove after tenderly testing # Set this to any custom RPC to override public endpoint -VITE_CUSTOM_RPC="https://virtual.mainnet.rpc.tenderly.co/e6243bfa-8701-4c53-af2b-ba435081669a" +VITE_CUSTOM_RPC="https://virtual.mainnet.rpc.tenderly.co/4817f636-347f-492b-82f0-778d2dfd051a" # Wallet Connect v2 project id VITE_WALLET_CONNECT_PROJECT_ID= From 062caa4389139743135d9691b921427245b94080 Mon Sep 17 00:00:00 2001 From: toniocodo Date: Tue, 23 Jul 2024 14:57:58 +0200 Subject: [PATCH 16/33] chore: update rpc, locale, gql --- apps/defi/.env | 2 +- apps/defi/src/lang/en.json | 172 ++++++++++++++++-- apps/defi/src/lang/extracts/en.json | 78 +++++++- .../shared/src/queries/snapshot.generated.ts | 51 +++++- .../proposals/src/snapshot.generated.ts | 51 +++++- 5 files changed, 324 insertions(+), 30 deletions(-) diff --git a/apps/defi/.env b/apps/defi/.env index aa8f0c724..efe806b35 100644 --- a/apps/defi/.env +++ b/apps/defi/.env @@ -1,6 +1,6 @@ # TODO remove after tenderly testing # Set this to any custom RPC to override public endpoint -VITE_CUSTOM_RPC="https://virtual.mainnet.rpc.tenderly.co/4817f636-347f-492b-82f0-778d2dfd051a" +VITE_CUSTOM_RPC="https://virtual.mainnet.rpc.tenderly.co/ddcbdc85-1370-4fe6-bae8-7b64bb0ba8dc" # Wallet Connect v2 project id VITE_WALLET_CONNECT_PROJECT_ID= diff --git a/apps/defi/src/lang/en.json b/apps/defi/src/lang/en.json index 10fa6269e..802508c74 100644 --- a/apps/defi/src/lang/en.json +++ b/apps/defi/src/lang/en.json @@ -1,4 +1,10 @@ { + "+0NTt9": [ + { + "type": 0, + "value": "Withdrawal request is taking a long time to process" + } + ], "+0zAiT": [ { "type": 0, @@ -59,6 +65,12 @@ "value": "Amount" } ], + "/2Xryp": [ + { + "type": 0, + "value": "Claimed Withdrawal" + } + ], "/6/sPX": [ { "type": 0, @@ -229,12 +241,6 @@ "value": "Return to Home Page" } ], - "2+4p9v": [ - { - "type": 0, - "value": "Claim tab" - } - ], "2/2yg+": [ { "type": 0, @@ -307,6 +313,12 @@ "value": "Legacy governance" } ], + "3cpPa4": [ + { + "type": 0, + "value": "Claiming your withdrawal will incur this estimated additional gas fee" + } + ], "3lOoIq": [ { "offset": 0, @@ -395,6 +407,12 @@ "value": "monthDuration" } ], + "3t3uoD": [ + { + "type": 0, + "value": "You have no withdrawal requests" + } + ], "3townk": [ { "type": 0, @@ -493,6 +511,12 @@ "value": "No description" } ], + "5yP3uI": [ + { + "type": 0, + "value": "Claim Withdrawal" + } + ], "5zH79K": [ { "type": 0, @@ -553,6 +577,12 @@ "value": "Amount to Stake" } ], + "7+beT+": [ + { + "type": 0, + "value": "~30 min - few days" + } + ], "7CPiAt": [ { "type": 0, @@ -893,6 +923,12 @@ "value": "Stablecoin mix" } ], + "DK7ein": [ + { + "type": 0, + "value": "Your pending amount" + } + ], "DKaqyQ": [ { "type": 0, @@ -991,6 +1027,12 @@ "value": "symbolOut" } ], + "EJv8r2": [ + { + "type": 0, + "value": "Refresh the page" + } + ], "EMU/OA": [ { "type": 0, @@ -1105,6 +1147,12 @@ "value": "Waiting for CCIP" } ], + "Gtdie8": [ + { + "type": 0, + "value": "Available to claim" + } + ], "H1+3mH": [ { "type": 0, @@ -1191,12 +1239,24 @@ "value": "Error while enabling rebasing" } ], + "IZFEUg": [ + { + "type": 0, + "value": "Ready" + } + ], "IfZsEo": [ { "type": 0, "value": "Vote against" } ], + "IuFETn": [ + { + "type": 0, + "value": "Duration" + } + ], "IzHsvX": [ { "type": 0, @@ -1371,6 +1431,12 @@ "value": "Reload Page" } ], + "MTN/Zf": [ + { + "type": 0, + "value": "Try to refresh the page and go to the Claim tab to see your withdrawal request" + } + ], "MW9FHt": [ { "type": 0, @@ -1575,6 +1641,12 @@ "value": "The length of time you will lock up your OGN in order to receive yield and voting power. Unstaking early carries a penalty relative to the remaining duration of the lockup" } ], + "PEzaGo": [ + { + "type": 0, + "value": "Request withdrawal" + } + ], "PFtMy9": [ { "type": 0, @@ -1617,6 +1689,12 @@ "value": "symbolOut" } ], + "Pkf9/r": [ + { + "type": 0, + "value": "This operation can take a few seconds to complete" + } + ], "PmkP1H": [ { "type": 0, @@ -1797,6 +1875,12 @@ "value": "count" } ], + "T1d+7b": [ + { + "type": 0, + "value": "Claiming Withdrawal" + } + ], "TIBoMl": [ { "type": 0, @@ -1889,6 +1973,12 @@ "value": "You are lawfully permitted to access this site. You understand and accept the risks associated with using the products in this dapp (OETH, OUSD, etc.)" } ], + "UjXhyn": [ + { + "type": 0, + "value": "Your requests" + } + ], "UkXeBW": [ { "type": 0, @@ -1959,6 +2049,12 @@ "value": "Origin Ether" } ], + "W7LOXq": [ + { + "type": 0, + "value": "Error while claiming withdrawal" + } + ], "W87PYU": [ { "type": 0, @@ -1999,6 +2095,12 @@ "value": "Redeem" } ], + "XrnF+v": [ + { + "type": 0, + "value": "Processing withdrawal request" + } + ], "Y/oE4U": [ { "type": 0, @@ -2275,12 +2377,6 @@ "value": "Connect Wallet" } ], - "cn8bYe": [ - { - "type": 0, - "value": "~10 days" - } - ], "d0kJUi": [ { "type": 0, @@ -2355,6 +2451,16 @@ "value": "Claiming Rewards" } ], + "dxLIdA": [ + { + "type": 0, + "value": "Claim" + }, + { + "type": 1, + "value": "amount" + } + ], "e+yfm6": [ { "type": 0, @@ -2671,12 +2777,6 @@ "value": "Stake OGN" } ], - "kJmZxj": [ - { - "type": 0, - "value": "Instant or async" - } - ], "kWMpjI": [ { "type": 0, @@ -2695,6 +2795,12 @@ "value": "Connect wallet to view" } ], + "lN55fl": [ + { + "type": 0, + "value": "Your withdrawal is being processed" + } + ], "lQmZjB": [ { "type": 0, @@ -2707,6 +2813,12 @@ "value": "Mins" } ], + "lc3LYh": [ + { + "type": 0, + "value": "Your claims" + } + ], "lozEho": [ { "type": 0, @@ -2891,6 +3003,24 @@ "value": "Error while bridging" } ], + "phZMsU": [ + { + "type": 0, + "value": "Claim " + }, + { + "type": 1, + "value": "amount" + }, + { + "type": 0, + "value": " " + }, + { + "type": 1, + "value": "symbolIn" + } + ], "qGZxc4": [ { "type": 0, @@ -3079,6 +3209,12 @@ "value": "Redeem amount" } ], + "uD4xKE": [ + { + "type": 0, + "value": "View withdrawal requests" + } + ], "uEFsHG": [ { "type": 0, diff --git a/apps/defi/src/lang/extracts/en.json b/apps/defi/src/lang/extracts/en.json index 9383e2f25..7c7795248 100644 --- a/apps/defi/src/lang/extracts/en.json +++ b/apps/defi/src/lang/extracts/en.json @@ -1,4 +1,7 @@ { + "+0NTt9": { + "defaultMessage": "Withdrawal request is taking a long time to process" + }, "+0zAiT": { "defaultMessage": "The updated amount of xOGN you will receive by adding OGN to this lockup." }, @@ -29,6 +32,9 @@ "/0TOL5": { "defaultMessage": "Amount" }, + "/2Xryp": { + "defaultMessage": "Claimed Withdrawal" + }, "/6/sPX": { "defaultMessage": "Docs" }, @@ -98,9 +104,6 @@ "1nxJrQ": { "defaultMessage": "Return to Home Page" }, - "2+4p9v": { - "defaultMessage": "Claim tab" - }, "2/2yg+": { "defaultMessage": "Add" }, @@ -137,9 +140,15 @@ "3at7Yr": { "defaultMessage": "Legacy governance" }, + "3cpPa4": { + "defaultMessage": "Claiming your withdrawal will incur this estimated additional gas fee" + }, "3lOoIq": { "defaultMessage": "{monthDuration,plural,=1{Extend lockup {lockupId} by {amount} {symbolIn} for # month} other{Extend lockup {lockupId} by {amount} {symbolIn} for # months}}" }, + "3t3uoD": { + "defaultMessage": "You have no withdrawal requests" + }, "3townk": { "defaultMessage": "Max vAPY" }, @@ -185,6 +194,9 @@ "5lVaeB": { "defaultMessage": "No description" }, + "5yP3uI": { + "defaultMessage": "Claim Withdrawal" + }, "5zH79K": { "defaultMessage": "Your veOGV staked positions" }, @@ -215,6 +227,9 @@ "6fzXU+": { "defaultMessage": "Amount to Stake" }, + "7+beT+": { + "defaultMessage": "~30 min - few days" + }, "7CPiAt": { "defaultMessage": "Redeemed" }, @@ -365,6 +380,9 @@ "DBP9Xf": { "defaultMessage": "Stablecoin mix" }, + "DK7ein": { + "defaultMessage": "Your pending amount" + }, "DKaqyQ": { "defaultMessage": "Redeeming" }, @@ -398,6 +416,9 @@ "EEwopl": { "defaultMessage": "{amountIn} {symbolIn} for {amountOut} {symbolOut}" }, + "EJv8r2": { + "defaultMessage": "Refresh the page" + }, "EMU/OA": { "defaultMessage": "The amount of xOGN you will receive today in return for your lockup. The more xOGN you have, the more voting power you have and the more staking rewards you will earn." }, @@ -449,6 +470,9 @@ "GtABHs": { "defaultMessage": "Waiting for CCIP" }, + "Gtdie8": { + "defaultMessage": "Available to claim" + }, "H1+3mH": { "defaultMessage": "A superior LST for earning yield across DeFi" }, @@ -482,9 +506,15 @@ "IP0AHa": { "defaultMessage": "Error while enabling rebasing" }, + "IZFEUg": { + "defaultMessage": "Ready" + }, "IfZsEo": { "defaultMessage": "Vote against" }, + "IuFETn": { + "defaultMessage": "Duration" + }, "IzHsvX": { "defaultMessage": "Est. gas:" }, @@ -566,6 +596,9 @@ "MSTVqC": { "defaultMessage": "Reload Page" }, + "MTN/Zf": { + "defaultMessage": "Try to refresh the page and go to the Claim tab to see your withdrawal request" + }, "MW9FHt": { "defaultMessage": "Ooops..." }, @@ -629,6 +662,9 @@ "P9sirH": { "defaultMessage": "The length of time you will lock up your OGN in order to receive yield and voting power. Unstaking early carries a penalty relative to the remaining duration of the lockup" }, + "PEzaGo": { + "defaultMessage": "Request withdrawal" + }, "PFtMy9": { "defaultMessage": "Canceled" }, @@ -638,6 +674,9 @@ "PdEKuc": { "defaultMessage": "{amtIn} {symbolIn} for {amtOut} {symbolOut}" }, + "Pkf9/r": { + "defaultMessage": "This operation can take a few seconds to complete" + }, "PmkP1H": { "defaultMessage": "Unsupported Network" }, @@ -707,6 +746,9 @@ "SzA4oV": { "defaultMessage": "{count,plural,=0{No address} =1{# address} other{# addresses}}" }, + "T1d+7b": { + "defaultMessage": "Claiming Withdrawal" + }, "TIBoMl": { "defaultMessage": "Total value locked {symbol}" }, @@ -731,6 +773,9 @@ "ULVduL": { "defaultMessage": "You are lawfully permitted to access this site. You understand and accept the risks associated with using the products in this dapp (OETH, OUSD, etc.)" }, + "UjXhyn": { + "defaultMessage": "Your requests" + }, "UkXeBW": { "defaultMessage": "If the problem persists, you can contact us through our {support}." }, @@ -758,6 +803,9 @@ "W33FNz": { "defaultMessage": "Origin Ether" }, + "W7LOXq": { + "defaultMessage": "Error while claiming withdrawal" + }, "W87PYU": { "defaultMessage": "View on {name}" }, @@ -776,6 +824,9 @@ "XSdWHA": { "defaultMessage": "Redeem" }, + "XrnF+v": { + "defaultMessage": "Processing withdrawal request" + }, "Y/oE4U": { "defaultMessage": "Calldata" }, @@ -884,9 +935,6 @@ "cg1VJ2": { "defaultMessage": "Connect Wallet" }, - "cn8bYe": { - "defaultMessage": "~10 days" - }, "d0kJUi": { "defaultMessage": "Connect your wallet to see your voting power" }, @@ -917,6 +965,9 @@ "dx9Xxj": { "defaultMessage": "Claiming Rewards" }, + "dxLIdA": { + "defaultMessage": "Claim{amount}" + }, "e+yfm6": { "defaultMessage": "Connect your wallet to see your balances" }, @@ -1055,9 +1106,6 @@ "kH1R79": { "defaultMessage": "Stake OGN" }, - "kJmZxj": { - "defaultMessage": "Instant or async" - }, "kWMpjI": { "defaultMessage": "Available on" }, @@ -1067,12 +1115,18 @@ "ksTDub": { "defaultMessage": "Connect wallet to view" }, + "lN55fl": { + "defaultMessage": "Your withdrawal is being processed" + }, "lQmZjB": { "defaultMessage": "Swap via Curve" }, "lb8m6m": { "defaultMessage": "Mins" }, + "lc3LYh": { + "defaultMessage": "Your claims" + }, "lozEho": { "defaultMessage": "Error while approving" }, @@ -1145,6 +1199,9 @@ "pYbH7c": { "defaultMessage": "Error while bridging" }, + "phZMsU": { + "defaultMessage": "Claim {amount} {symbolIn}" + }, "qGZxc4": { "defaultMessage": "Connect your wallet to

select the network" }, @@ -1232,6 +1289,9 @@ "u53ROb": { "defaultMessage": "Redeem amount" }, + "uD4xKE": { + "defaultMessage": "View withdrawal requests" + }, "uEFsHG": { "defaultMessage": "Discord forum" }, diff --git a/libs/defi/shared/src/queries/snapshot.generated.ts b/libs/defi/shared/src/queries/snapshot.generated.ts index 679bba348..943187aa8 100644 --- a/libs/defi/shared/src/queries/snapshot.generated.ts +++ b/libs/defi/shared/src/queries/snapshot.generated.ts @@ -91,6 +91,42 @@ export type Item = { spacesCount?: Maybe; }; +export type Leaderboard = { + __typename?: 'Leaderboard'; + lastVote?: Maybe; + proposalsCount?: Maybe; + space?: Maybe; + user?: Maybe; + votesCount?: Maybe; +}; + +export type LeaderboardsWhere = { + proposal_count?: InputMaybe; + proposal_count_gt?: InputMaybe>>; + proposal_count_gte?: InputMaybe>>; + proposal_count_in?: InputMaybe>>; + proposal_count_lt?: InputMaybe>>; + proposal_count_lte?: InputMaybe>>; + proposal_count_not?: InputMaybe; + proposal_count_not_in?: InputMaybe>>; + space?: InputMaybe; + space_in?: InputMaybe>>; + space_not?: InputMaybe; + space_not_in?: InputMaybe>>; + user?: InputMaybe; + user_in?: InputMaybe>>; + user_not?: InputMaybe; + user_not_in?: InputMaybe>>; + vote_count?: InputMaybe; + vote_count_gt?: InputMaybe>>; + vote_count_gte?: InputMaybe>>; + vote_count_in?: InputMaybe>>; + vote_count_lt?: InputMaybe>>; + vote_count_lte?: InputMaybe>>; + vote_count_not?: InputMaybe; + vote_count_not_in?: InputMaybe>>; +}; + export type Message = { __typename?: 'Message'; address?: Maybe; @@ -231,6 +267,7 @@ export type Query = { __typename?: 'Query'; aliases?: Maybe>>; follows?: Maybe>>; + leaderboards?: Maybe>>; messages?: Maybe>>; networks?: Maybe>>; plugins?: Maybe>>; @@ -273,6 +310,15 @@ export type QueryFollowsArgs = { }; +export type QueryLeaderboardsArgs = { + first?: Scalars['Int']['input']; + orderBy?: InputMaybe; + orderDirection?: InputMaybe; + skip?: Scalars['Int']['input']; + where?: InputMaybe; +}; + + export type QueryMessagesArgs = { first?: Scalars['Int']['input']; orderBy?: InputMaybe; @@ -579,14 +625,17 @@ export type User = { about?: Maybe; avatar?: Maybe; cover?: Maybe; - created: Scalars['Int']['output']; + created?: Maybe; farcaster?: Maybe; github?: Maybe; id: Scalars['String']['output']; ipfs?: Maybe; + lastVote?: Maybe; lens?: Maybe; name?: Maybe; + proposalsCount?: Maybe; twitter?: Maybe; + votesCount?: Maybe; }; export type UsersWhere = { diff --git a/libs/governance/proposals/src/snapshot.generated.ts b/libs/governance/proposals/src/snapshot.generated.ts index 0604134b4..621d30bdd 100644 --- a/libs/governance/proposals/src/snapshot.generated.ts +++ b/libs/governance/proposals/src/snapshot.generated.ts @@ -91,6 +91,42 @@ export type Item = { spacesCount?: Maybe; }; +export type Leaderboard = { + __typename?: 'Leaderboard'; + lastVote?: Maybe; + proposalsCount?: Maybe; + space?: Maybe; + user?: Maybe; + votesCount?: Maybe; +}; + +export type LeaderboardsWhere = { + proposal_count?: InputMaybe; + proposal_count_gt?: InputMaybe>>; + proposal_count_gte?: InputMaybe>>; + proposal_count_in?: InputMaybe>>; + proposal_count_lt?: InputMaybe>>; + proposal_count_lte?: InputMaybe>>; + proposal_count_not?: InputMaybe; + proposal_count_not_in?: InputMaybe>>; + space?: InputMaybe; + space_in?: InputMaybe>>; + space_not?: InputMaybe; + space_not_in?: InputMaybe>>; + user?: InputMaybe; + user_in?: InputMaybe>>; + user_not?: InputMaybe; + user_not_in?: InputMaybe>>; + vote_count?: InputMaybe; + vote_count_gt?: InputMaybe>>; + vote_count_gte?: InputMaybe>>; + vote_count_in?: InputMaybe>>; + vote_count_lt?: InputMaybe>>; + vote_count_lte?: InputMaybe>>; + vote_count_not?: InputMaybe; + vote_count_not_in?: InputMaybe>>; +}; + export type Message = { __typename?: 'Message'; address?: Maybe; @@ -231,6 +267,7 @@ export type Query = { __typename?: 'Query'; aliases?: Maybe>>; follows?: Maybe>>; + leaderboards?: Maybe>>; messages?: Maybe>>; networks?: Maybe>>; plugins?: Maybe>>; @@ -273,6 +310,15 @@ export type QueryFollowsArgs = { }; +export type QueryLeaderboardsArgs = { + first?: Scalars['Int']['input']; + orderBy?: InputMaybe; + orderDirection?: InputMaybe; + skip?: Scalars['Int']['input']; + where?: InputMaybe; +}; + + export type QueryMessagesArgs = { first?: Scalars['Int']['input']; orderBy?: InputMaybe; @@ -579,14 +625,17 @@ export type User = { about?: Maybe; avatar?: Maybe; cover?: Maybe; - created: Scalars['Int']['output']; + created?: Maybe; farcaster?: Maybe; github?: Maybe; id: Scalars['String']['output']; ipfs?: Maybe; + lastVote?: Maybe; lens?: Maybe; name?: Maybe; + proposalsCount?: Maybe; twitter?: Maybe; + votesCount?: Maybe; }; export type UsersWhere = { From 15ad061a4483fce5649063540b116d60073310d3 Mon Sep 17 00:00:00 2001 From: toniocodo Date: Tue, 23 Jul 2024 14:58:12 +0200 Subject: [PATCH 17/33] feat: update withdraw delay --- libs/defi/oeth/src/redeem/components/RedeemActionCard.tsx | 3 +++ libs/defi/oeth/src/redeem/constants.ts | 6 +++++- libs/defi/oeth/src/redeem/hooks.ts | 8 ++++++-- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/libs/defi/oeth/src/redeem/components/RedeemActionCard.tsx b/libs/defi/oeth/src/redeem/components/RedeemActionCard.tsx index c9dd6b5a3..574781841 100644 --- a/libs/defi/oeth/src/redeem/components/RedeemActionCard.tsx +++ b/libs/defi/oeth/src/redeem/components/RedeemActionCard.tsx @@ -6,6 +6,8 @@ import { isNilOrEmpty } from '@origin/shared/utils'; import { format, from } from 'dnum'; import { useIntl } from 'react-intl'; +import { WITHDRAW_DELAY } from '../constants'; + import type { CardProps, TypographyProps } from '@mui/material'; import type { ValueLabelProps } from '@origin/shared/components'; import type { SwapRoute } from '@origin/shared/providers'; @@ -124,6 +126,7 @@ export const RedeemActionCard = ({ intl.formatMessage( (route as SwapRoute)?.meta ?.waitTime ?? { defaultMessage: '~1 min' }, + { WITHDRAW_DELAY }, ) ) } diff --git a/libs/defi/oeth/src/redeem/constants.ts b/libs/defi/oeth/src/redeem/constants.ts index 45309f004..31d81a092 100644 --- a/libs/defi/oeth/src/redeem/constants.ts +++ b/libs/defi/oeth/src/redeem/constants.ts @@ -6,6 +6,8 @@ import type { SwapRoute } from '@origin/shared/providers'; import type { Meta, OethRedeemAction } from './types'; +export const WITHDRAW_DELAY = 10; // minutes + export const GAS_BUFFER = 10n; // 10% export const redeemRoutes: SwapRoute[] = [ @@ -35,7 +37,9 @@ export const redeemRoutes: SwapRoute[] = [ action: 'redeem-vault-async', meta: { icon: OETH, - waitTime: defineMessage({ defaultMessage: '~30 min - few days' }), + waitTime: defineMessage({ + defaultMessage: `~{WITHDRAW_DELAY} min - few days`, + }), waitTimeColor: 'warning.main', }, }, diff --git a/libs/defi/oeth/src/redeem/hooks.ts b/libs/defi/oeth/src/redeem/hooks.ts index a122f2243..15d7ee199 100644 --- a/libs/defi/oeth/src/redeem/hooks.ts +++ b/libs/defi/oeth/src/redeem/hooks.ts @@ -8,6 +8,7 @@ import { addMinutes, fromUnixTime, isAfter } from 'date-fns'; import { useSearchParams } from 'react-router-dom'; import { useAccount, useConfig } from 'wagmi'; +import { WITHDRAW_DELAY } from './constants'; import { useWithdrawalRequestsQuery } from './queries.generated'; import type { HexAddress } from '@origin/shared/utils'; @@ -75,7 +76,7 @@ export const useWithdrawalRequests = ( ]); const queueData = isFulfilled(res[0]) ? res[0].value : null; const requests = isFulfilled(res[1]) - ? res[1].value?.oethWithdrawalRequests ?? [] + ? (res[1].value?.oethWithdrawalRequests ?? []) : []; const block = isFulfilled(res[2]) ? res[2].value : null; @@ -85,7 +86,10 @@ export const useWithdrawalRequests = ( BigInt(r.queued) <= BigInt(queueData?.claimable ?? 0) && isAfter( new Date(r.timestamp), - addMinutes(fromUnixTime(Number(block?.timestamp ?? 0)), 30), + addMinutes( + fromUnixTime(Number(block?.timestamp ?? 0)), + WITHDRAW_DELAY, + ), ); return { From 6892951e5fdf0414d333a25865f54320046c3035 Mon Sep 17 00:00:00 2001 From: toniocodo Date: Wed, 24 Jul 2024 18:54:43 +0200 Subject: [PATCH 18/33] feat: refresh claims after wait, locales --- apps/defi/src/lang/en.json | 20 +++++++++++++------ apps/defi/src/lang/extracts/en.json | 6 +++--- .../src/redeem/components/ClaimHeader.tsx | 10 ++-------- .../components/WithdrawalRequestModal.tsx | 5 +++++ libs/defi/oeth/src/redeem/hooks.ts | 2 +- 5 files changed, 25 insertions(+), 18 deletions(-) diff --git a/apps/defi/src/lang/en.json b/apps/defi/src/lang/en.json index 802508c74..8a011bf3a 100644 --- a/apps/defi/src/lang/en.json +++ b/apps/defi/src/lang/en.json @@ -577,12 +577,6 @@ "value": "Amount to Stake" } ], - "7+beT+": [ - { - "type": 0, - "value": "~30 min - few days" - } - ], "7CPiAt": [ { "type": 0, @@ -667,6 +661,20 @@ "value": "Redeem for mix via Origin Vault" } ], + "8g703D": [ + { + "type": 0, + "value": "~" + }, + { + "type": 1, + "value": "WITHDRAW_DELAY" + }, + { + "type": 0, + "value": " min - few days" + } + ], "8nvhZ9": [ { "type": 0, diff --git a/apps/defi/src/lang/extracts/en.json b/apps/defi/src/lang/extracts/en.json index 7c7795248..42600e128 100644 --- a/apps/defi/src/lang/extracts/en.json +++ b/apps/defi/src/lang/extracts/en.json @@ -227,9 +227,6 @@ "6fzXU+": { "defaultMessage": "Amount to Stake" }, - "7+beT+": { - "defaultMessage": "~30 min - few days" - }, "7CPiAt": { "defaultMessage": "Redeemed" }, @@ -272,6 +269,9 @@ "8cCxx8": { "defaultMessage": "Redeem for mix via Origin Vault" }, + "8g703D": { + "defaultMessage": "~{WITHDRAW_DELAY} min - few days" + }, "8nvhZ9": { "defaultMessage": "Last" }, diff --git a/libs/defi/oeth/src/redeem/components/ClaimHeader.tsx b/libs/defi/oeth/src/redeem/components/ClaimHeader.tsx index ccaa02c21..9d15e6ae1 100644 --- a/libs/defi/oeth/src/redeem/components/ClaimHeader.tsx +++ b/libs/defi/oeth/src/redeem/components/ClaimHeader.tsx @@ -24,18 +24,12 @@ export const ClaimHeader = (props: StackProps) => { ); const availableToClaim = claimable?.reduce( - (acc, curr) => - curr.claimable - ? add([curr.amount, tokens.mainnet.WETH.decimals], acc) - : acc, + (acc, curr) => add([curr.amount, tokens.mainnet.WETH.decimals], acc), from(0), ) ?? from(0); const pendingAmount = pending?.reduce( - (acc, curr) => - curr.claimable - ? add([curr.amount, tokens.mainnet.WETH.decimals], acc) - : acc, + (acc, curr) => add([curr.amount, tokens.mainnet.WETH.decimals], acc), from(0), ) ?? from(0); diff --git a/libs/defi/oeth/src/redeem/components/WithdrawalRequestModal.tsx b/libs/defi/oeth/src/redeem/components/WithdrawalRequestModal.tsx index d98b677db..eac71e945 100644 --- a/libs/defi/oeth/src/redeem/components/WithdrawalRequestModal.tsx +++ b/libs/defi/oeth/src/redeem/components/WithdrawalRequestModal.tsx @@ -22,6 +22,7 @@ import { import { BlockExplorerLink } from '@origin/shared/providers'; import { getFormatPrecision, ZERO_ADDRESS } from '@origin/shared/utils'; import { useIntervalEffect, usePrevious } from '@react-hookz/web'; +import { useQueryClient } from '@tanstack/react-query'; import { format } from 'dnum'; import { useIntl } from 'react-intl'; import { useAccount } from 'wagmi'; @@ -58,6 +59,7 @@ export const WithdrawalRequestModal = ({ const theme = useTheme(); const fullScreen = useMediaQuery(theme.breakpoints.down('md')); const { update } = useViewSelect(); + const queryClient = useQueryClient(); const { address } = useAccount(); const [status, setStatus] = useState('processing'); const [retries, setRetries] = useState(0); @@ -207,6 +209,9 @@ export const WithdrawalRequestModal = ({ fullWidth onClick={() => { update('claim'); + queryClient.invalidateQueries({ + queryKey: ['useClaimableRequests', address], + }); onClose?.({}, 'backdropClick'); }} size="large" diff --git a/libs/defi/oeth/src/redeem/hooks.ts b/libs/defi/oeth/src/redeem/hooks.ts index 15d7ee199..b5ca6dcf9 100644 --- a/libs/defi/oeth/src/redeem/hooks.ts +++ b/libs/defi/oeth/src/redeem/hooks.ts @@ -88,7 +88,7 @@ export const useWithdrawalRequests = ( new Date(r.timestamp), addMinutes( fromUnixTime(Number(block?.timestamp ?? 0)), - WITHDRAW_DELAY, + WITHDRAW_DELAY + 1, ), ); From 73c91bbbe44bf9597ccecb2f58f95ac1290db41f Mon Sep 17 00:00:00 2001 From: toniocodo Date: Thu, 25 Jul 2024 09:28:16 +0200 Subject: [PATCH 19/33] feat: time based delay check, switch width fix --- .../oeth/src/redeem/components/ClaimForm.tsx | 12 +++++++--- libs/defi/oeth/src/redeem/hooks.ts | 23 ++++++++----------- .../components/src/Switches/SliderSwitch.tsx | 1 + 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/libs/defi/oeth/src/redeem/components/ClaimForm.tsx b/libs/defi/oeth/src/redeem/components/ClaimForm.tsx index a6664ac9e..fce1f9a77 100644 --- a/libs/defi/oeth/src/redeem/components/ClaimForm.tsx +++ b/libs/defi/oeth/src/redeem/components/ClaimForm.tsx @@ -57,7 +57,7 @@ export const ClaimForm = (props: StackProps) => { : { contract: contracts.mainnet.OETHVault, functionName: 'claimWithdrawals', - args: selectedClaimIds, + args: [selectedClaimIds], }; const selectedAmount = useMemo( @@ -101,7 +101,7 @@ export const ClaimForm = (props: StackProps) => { }; return ( - + { spacing={1} p={2} justifyContent="space-between" + {...rest} > } label={ - + {format(amt, getFormatPrecision(amt))} diff --git a/libs/defi/oeth/src/redeem/hooks.ts b/libs/defi/oeth/src/redeem/hooks.ts index b5ca6dcf9..e7c736ca7 100644 --- a/libs/defi/oeth/src/redeem/hooks.ts +++ b/libs/defi/oeth/src/redeem/hooks.ts @@ -3,8 +3,8 @@ import { useMemo } from 'react'; import { contracts } from '@origin/shared/contracts'; import { isFulfilled, ZERO_ADDRESS } from '@origin/shared/utils'; import { useQuery, useQueryClient } from '@tanstack/react-query'; -import { getBlock, readContract } from '@wagmi/core'; -import { addMinutes, fromUnixTime, isAfter } from 'date-fns'; +import { readContract } from '@wagmi/core'; +import { addMinutes, isAfter } from 'date-fns'; import { useSearchParams } from 'react-router-dom'; import { useAccount, useConfig } from 'wagmi'; @@ -69,27 +69,24 @@ export const useWithdrawalRequests = ( address: address ?? ZERO_ADDRESS, }), }), - getBlock(config, { - blockTag: 'finalized', - chainId: contracts.mainnet.OETHVault.chainId, - }), ]); const queueData = isFulfilled(res[0]) ? res[0].value : null; const requests = isFulfilled(res[1]) ? (res[1].value?.oethWithdrawalRequests ?? []) : []; - const block = isFulfilled(res[2]) ? res[2].value : null; - + console.log(queueData); return requests.map((r) => { + console.log( + r.queued, + queueData?.claimable, + BigInt(r.queued) <= BigInt(queueData?.claimable ?? 0), + ); const claimable = !r.claimed && BigInt(r.queued) <= BigInt(queueData?.claimable ?? 0) && isAfter( - new Date(r.timestamp), - addMinutes( - fromUnixTime(Number(block?.timestamp ?? 0)), - WITHDRAW_DELAY + 1, - ), + new Date(), + addMinutes(new Date(r.timestamp), WITHDRAW_DELAY + 1), ); return { diff --git a/libs/shared/components/src/Switches/SliderSwitch.tsx b/libs/shared/components/src/Switches/SliderSwitch.tsx index 807908706..8026293bb 100644 --- a/libs/shared/components/src/Switches/SliderSwitch.tsx +++ b/libs/shared/components/src/Switches/SliderSwitch.tsx @@ -81,6 +81,7 @@ export const SliderSwitch = ({ zIndex: 1, top: 0, left: 0, + right: 0, width: itemsWidth[idx], height: 1, transform: `translateX(${translateX}px)`, From 059fee64ca6cfa395df7ff8cee1ebd3882f4cba9 Mon Sep 17 00:00:00 2001 From: toniocodo Date: Thu, 25 Jul 2024 12:25:45 +0200 Subject: [PATCH 20/33] fix: remove logging --- libs/defi/oeth/src/redeem/hooks.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/libs/defi/oeth/src/redeem/hooks.ts b/libs/defi/oeth/src/redeem/hooks.ts index e7c736ca7..cae994857 100644 --- a/libs/defi/oeth/src/redeem/hooks.ts +++ b/libs/defi/oeth/src/redeem/hooks.ts @@ -74,13 +74,7 @@ export const useWithdrawalRequests = ( const requests = isFulfilled(res[1]) ? (res[1].value?.oethWithdrawalRequests ?? []) : []; - console.log(queueData); return requests.map((r) => { - console.log( - r.queued, - queueData?.claimable, - BigInt(r.queued) <= BigInt(queueData?.claimable ?? 0), - ); const claimable = !r.claimed && BigInt(r.queued) <= BigInt(queueData?.claimable ?? 0) && From 1a4affacef53f5121a47536728af1aa5ddbbf878 Mon Sep 17 00:00:00 2001 From: toniocodo Date: Thu, 25 Jul 2024 23:29:28 +0200 Subject: [PATCH 21/33] fix: slider switch width --- libs/shared/components/src/Switches/SliderSwitch.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/shared/components/src/Switches/SliderSwitch.tsx b/libs/shared/components/src/Switches/SliderSwitch.tsx index 8026293bb..e2c0422f4 100644 --- a/libs/shared/components/src/Switches/SliderSwitch.tsx +++ b/libs/shared/components/src/Switches/SliderSwitch.tsx @@ -1,4 +1,4 @@ -import { forwardRef, useLayoutEffect, useRef, useState } from 'react'; +import { forwardRef, useEffect, useRef, useState } from 'react'; import { Box, Button, emphasize, Stack, Typography } from '@mui/material'; import { isNilOrEmpty } from '@origin/shared/utils'; @@ -28,9 +28,9 @@ export const SliderSwitch = ({ const refs = useRef([]); const [itemsWidth, setItemsWidth] = useState([]); - useLayoutEffect(() => { + useEffect(() => { setItemsWidth(refs.current.map((o) => o.offsetWidth)); - }, []); + }, [options]); const idx = options.findIndex((o) => isNilOrEmpty(o.value) ? isNilOrEmpty(value) : o.value === value, From c9f9f67919cad42d51b1aa2134cd5c31d3eee3a9 Mon Sep 17 00:00:00 2001 From: toniocodo Date: Thu, 25 Jul 2024 23:29:50 +0200 Subject: [PATCH 22/33] feat: add refresher hook for long lived processes --- libs/shared/providers/src/index.ts | 1 + libs/shared/providers/src/refresher/hooks.ts | 81 ++++++++++++++++++++ libs/shared/providers/src/refresher/index.ts | 1 + 3 files changed, 83 insertions(+) create mode 100644 libs/shared/providers/src/refresher/hooks.ts create mode 100644 libs/shared/providers/src/refresher/index.ts diff --git a/libs/shared/providers/src/index.ts b/libs/shared/providers/src/index.ts index e880451bd..12f603e31 100644 --- a/libs/shared/providers/src/index.ts +++ b/libs/shared/providers/src/index.ts @@ -11,6 +11,7 @@ export * from './notifications'; export * from './prices'; export * from './rebaseBanner'; export * from './redeemer'; +export * from './refresher'; export * from './settings'; export * from './slippage'; export * from './swapper'; diff --git a/libs/shared/providers/src/refresher/hooks.ts b/libs/shared/providers/src/refresher/hooks.ts new file mode 100644 index 000000000..e4ecafb3e --- /dev/null +++ b/libs/shared/providers/src/refresher/hooks.ts @@ -0,0 +1,81 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { useCallback, useState } from 'react'; + +import { useIntervalEffect } from '@react-hookz/web'; +import { useQueryClient } from '@tanstack/react-query'; + +import type { QueryFunction, QueryKey } from '@tanstack/react-query'; + +export type RefreshStatus = + | 'idle' + | 'polling' + | 'processed' + | 'timeout' + | 'error'; + +export type UseRefresherProps = { + queryKey: QueryKey; + queryFn: QueryFunction; + isResultProcessed: (prev: QueryResult, next: QueryResult) => boolean; + maxRetries?: number; + interval?: number; +}; + +export const useRefresher = ({ + queryKey, + queryFn, + isResultProcessed, + maxRetries = 10, + interval = 2000, +}: UseRefresherProps) => { + const queryClient = useQueryClient(); + const prev = queryClient.getQueryData(queryKey); + const [retries, setRetries] = useState(0); + const [status, setStatus] = useState('idle'); + const [pollInterval, setPollInterval] = useState( + undefined, + ); + + const startRefresh = useCallback(() => { + setPollInterval(interval); + setStatus('polling'); + }, [interval]); + + const stopRefresh = useCallback(() => { + setPollInterval(undefined); + setStatus('idle'); + }, []); + + useIntervalEffect(() => { + (async () => { + const next = await queryClient.fetchQuery({ + queryKey, + queryFn, + staleTime: 0, + }); + + try { + if (!prev || !next) { + setPollInterval(undefined); + setStatus('error'); + } else if (retries > maxRetries) { + setPollInterval(undefined); + setStatus('timeout'); + } else if (isResultProcessed(prev, next)) { + setPollInterval(undefined); + setStatus('processed'); + } + } catch { + setPollInterval(undefined); + setStatus('error'); + } + setRetries((prev) => prev + 1); + })(); + }, pollInterval); + + return { + status, + startRefresh, + stopRefresh, + }; +}; diff --git a/libs/shared/providers/src/refresher/index.ts b/libs/shared/providers/src/refresher/index.ts new file mode 100644 index 000000000..4cc90d02b --- /dev/null +++ b/libs/shared/providers/src/refresher/index.ts @@ -0,0 +1 @@ +export * from './hooks'; From 7774e1ea51de72f3f6f2402d1df6b25683dde1a8 Mon Sep 17 00:00:00 2001 From: toniocodo Date: Thu, 25 Jul 2024 23:30:09 +0200 Subject: [PATCH 23/33] feat: use refresher for oeth redeems --- .../oeth/src/redeem/components/ClaimForm.tsx | 89 ++++++++++----- .../components/WithdrawalRequestModal.tsx | 80 +++++++------- libs/defi/oeth/src/redeem/hooks.ts | 103 +++++++++++------- 3 files changed, 160 insertions(+), 112 deletions(-) diff --git a/libs/defi/oeth/src/redeem/components/ClaimForm.tsx b/libs/defi/oeth/src/redeem/components/ClaimForm.tsx index fce1f9a77..8db407fd9 100644 --- a/libs/defi/oeth/src/redeem/components/ClaimForm.tsx +++ b/libs/defi/oeth/src/redeem/components/ClaimForm.tsx @@ -1,4 +1,4 @@ -import { useMemo, useState } from 'react'; +import { useEffect, useMemo, useState } from 'react'; import { Button, @@ -18,7 +18,7 @@ import { FaCircleCheckRegular, FaClockRegular, } from '@origin/shared/icons'; -import { TxButton } from '@origin/shared/providers'; +import { TxButton, useRefresher } from '@origin/shared/providers'; import { getFormatPrecision, isNilOrEmpty, @@ -28,10 +28,9 @@ import { useQueryClient } from '@tanstack/react-query'; import { add, eq, format, from } from 'dnum'; import { remove } from 'ramda'; import { useIntl } from 'react-intl'; -import { useAccount } from 'wagmi'; +import { useAccount, useConfig } from 'wagmi'; import { useWithdrawalRequests } from '../hooks'; -import { useWithdrawalRequestsQuery } from '../queries.generated'; import type { StackProps } from '@mui/material'; import type { Dnum } from 'dnum'; @@ -40,13 +39,21 @@ import type { WithdrawalRequest } from '../types'; export const ClaimForm = (props: StackProps) => { const intl = useIntl(); - const queryClient = useQueryClient(); const { address } = useAccount(); + const config = useConfig(); + const queryClient = useQueryClient(); const [selectedClaimIds, setSelectedClaimIds] = useState([]); const { data: requests, isLoading: isRequestsLoading } = useWithdrawalRequests({ select: (data) => data?.filter((r) => !r.claimed), }); + const { startRefresh, status } = useRefresher({ + queryKey: useWithdrawalRequests.getKey(address ?? ZERO_ADDRESS), + queryFn: useWithdrawalRequests.fetcher(config, queryClient), + isResultProcessed: (prev, next) => + prev.filter((r) => r.claimed).length < + next.filter((r) => r.claimed).length, + }); const args = selectedClaimIds.length === 1 ? { @@ -59,7 +66,6 @@ export const ClaimForm = (props: StackProps) => { functionName: 'claimWithdrawals', args: [selectedClaimIds], }; - const selectedAmount = useMemo( () => selectedClaimIds.reduce((acc, curr) => { @@ -73,13 +79,7 @@ export const ClaimForm = (props: StackProps) => { params: args as any, callbacks: { onWriteSuccess: () => { - queryClient.invalidateQueries({ - queryKey: [ - useWithdrawalRequestsQuery.getKey({ - address: address ?? ZERO_ADDRESS, - }), - ], - }); + startRefresh(); }, }, activity: { @@ -91,6 +91,13 @@ export const ClaimForm = (props: StackProps) => { enableGas: true, }); + useEffect(() => { + if (['timeout', 'processed', 'error'].includes(status)) { + setSelectedClaimIds([]); + queryClient.invalidateQueries(); + } + }, [address, queryClient, status]); + const handleClaimClick = (requestId: bigint) => () => { const idx = selectedClaimIds.findIndex((id) => id === requestId); if (idx === -1) { @@ -133,6 +140,9 @@ export const ClaimForm = (props: StackProps) => { request={r} selected={selectedClaimIds.includes(r.requestId)} onSelect={handleClaimClick(r.requestId)} + isProcessing={ + selectedClaimIds.includes(r.requestId) && status === 'polling' + } /> )) )} @@ -159,7 +169,7 @@ export const ClaimForm = (props: StackProps) => { params={params} callbacks={callbacks} variant="action" - disabled={isNilOrEmpty(selectedClaimIds)} + disabled={isNilOrEmpty(selectedClaimIds) || status === 'polling'} label={intl.formatMessage( { defaultMessage: 'Claim{amount}' }, { @@ -177,10 +187,18 @@ type ClaimRowProps = { request: WithdrawalRequest; selected: boolean; onSelect: () => void; + isProcessing: boolean; } & StackProps; -const ClaimRow = ({ request, selected, onSelect, ...rest }: ClaimRowProps) => { +const ClaimRow = ({ + request, + selected, + onSelect, + isProcessing, + ...rest +}: ClaimRowProps) => { const amt = [request?.amount ?? 0n, tokens.mainnet.WETH.decimals] as Dnum; + const disabled = !request.claimable || isProcessing; return ( { } onChange={onSelect} - disabled={!request.claimable} + disabled={disabled} disableTypography /> - + ), - processing: ( + polling: (