Skip to content

Commit

Permalink
Feat/wagmi vaults (#208)
Browse files Browse the repository at this point in the history
* feat: wagmi in vaults

* lint: all \t to spaces for const, let and functions (#209)

* fix: lint

* fix: lint

* Feat/wagmi veyfi (#210)

* feat: migrate to wagmi

* Update pages/vaults/factory.tsx

* Feat/wagmi yBribe (#211)

* feat: migrate to wagmi

* Feat/wagmi ybal (#214)

* feat: init yBal

* fix: lint

* Update apps/common/components/AppHeader.tsx

Co-authored-by: Chef Karelian <78794805+karelianpie@users.noreply.github.com>

* fix: remove unused test prop

* feat: refactor useCurrentApp

* fix: reduce lines

* fix: extract HeadLabel

* fix: add more strict checks

* fix: reduce complexity

* fix: extract Row

* fix: invalid code

* fix: possible undef

* feat: update lib and var names

* feat: update options from/to

* wip: yBal no yCRV

* fix: remove veBal

* feat: cleaning imports and options

* feat: bal zap integration WIP

* fix: onCatchError

* test: yBal actions#zaap

* test: simulateZapForMinOut

* refactor: Expect zap to be called with BigNumber

* feat: update lib and var names

* feat: new contract version

* wip: ugly

* fix: Ethers mock

* feat: Mock providers

* fix: invalid BigNumber value

* feat: update tests

* feat: always test

* fix: switch env to node for tests

* fix: remove some logs

* feat: wip yBal

* feat: wip yBal

* feat: ylock ui

* feat: useFetch for fetching stybal vault (#202)

Co-authored-by: Major <90963895+Majorfi@users.noreply.github.com>

* fix: conflicts and yCRV clean

* feat: smol refactor

* feat: yBal pull

* feat: yBal migration

* fix: spacings

* fix: slippage

* fix: remove extra props for arrow down

* fix: add sentry to handleSettle

* fix: tabs

* Update apps/ycrv/utils/actions.ts

Co-authored-by: Chef Karelian <78794805+karelianpie@users.noreply.github.com>

* fix: set const

* fix: set const

* feat: update solvers (#217)

* feat: update solvers

* fix: dynamic imports

* fix: some lint issues

* fix: removing wdyu

* fix: remove log

* fix: enable

* fix: endpoint to path

* Feat/wagmi address (#219)

* feat: remove all wagmiAddress

* fix: linting

* fix: typing issues

* fix: remove useless assert and add namecheck

* fix: remove duplicate import

* Update apps/vaults/contexts/useStakingRewards.tsx

Co-authored-by: Chef Karelian <78794805+karelianpie@users.noreply.github.com>

* Feat/wagmi-bribesfix (#220)

* feat: remove v3 declaration

* fix: transform strings to addresses

* fix: bribe results

* fix: revert ui changes. Later

* fix: some bit of UI

* fix: responsiveness

* Update apps/common/schemas/curveSchemas.ts

Co-authored-by: Chef Karelian <78794805+karelianpie@users.noreply.github.com>

* fix: transform toAddress easy mode

* feat/Refactor tx handlers (#222)

* feat: wagmi handleTX init

* fix: remove some level of complexity

* feat: migrate the common actions

* feat: suggestion to make bigInt |undefined to be sure to check stuff

* fix: remove stupid suggestion

* feat: migrate actions

* fix: Types

* fix: Cannot set bigint to type undefined

* Update apps/common/utils/toWagmiProvider.tsx

* fix: remove useless toString() (#223)

---------

Co-authored-by: Karelian Pie <devkarelianpie@gmail.com>

---------

Co-authored-by: Chef Karelian <78794805+karelianpie@users.noreply.github.com>
Co-authored-by: Karelian Pie <devkarelianpie@gmail.com>

---------

Co-authored-by: Chef Karelian <78794805+karelianpie@users.noreply.github.com>
Co-authored-by: Karelian Pie <devkarelianpie@gmail.com>

---------

Co-authored-by: Chef Karelian <78794805+karelianpie@users.noreply.github.com>
Co-authored-by: Karelian Pie <devkarelianpie@gmail.com>

---------

Co-authored-by: Chef Karelian <78794805+karelianpie@users.noreply.github.com>
Co-authored-by: Karelian Pie <devkarelianpie@gmail.com>

---------

Co-authored-by: Chef Karelian <78794805+karelianpie@users.noreply.github.com>
Co-authored-by: Karelian Pie <devkarelianpie@gmail.com>

---------

Co-authored-by: Chef Karelian <78794805+karelianpie@users.noreply.github.com>
Co-authored-by: Karelian Pie <devkarelianpie@gmail.com>

---------

Co-authored-by: Chef Karelian <78794805+karelianpie@users.noreply.github.com>
Co-authored-by: Karelian Pie <devkarelianpie@gmail.com>
  • Loading branch information
3 people authored Jun 2, 2023
1 parent 8c5f10d commit a2a7196
Show file tree
Hide file tree
Showing 184 changed files with 7,412 additions and 7,038 deletions.
3 changes: 2 additions & 1 deletion .eslintignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Auto Generated PWA files
public/sw*
public/workbox*
ipfs/*
ipfs/*
public/worker*
4 changes: 1 addition & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ name: Test

on:
push:
branches:
- main
pull_request:
workflow_dispatch:

Expand All @@ -25,4 +23,4 @@ jobs:
run: yarn --prefer-offline

- name: Test project
run: yarn node --experimental-vm-modules $(yarn bin jest)
run: yarn test
4 changes: 2 additions & 2 deletions apps/common/components/AmountInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,13 @@ function AmountInput({
min={0}
aria-label={label}
value={displayedAmount}
onChange={onAmountChange ? (e) => onAmountChange(e.target.value) : undefined}
onChange={onAmountChange ? (e): void => onAmountChange(e.target.value) : undefined}
placeholder={loading ? '' : placeholder ?? '0'}
disabled={disabled}
/>
<Renderable shouldRender={!!maxAmount && !disabled}>
<button
onClick={onMaxClick ? () => onMaxClick() : undefined}
onClick={onMaxClick ? (): void => onMaxClick() : undefined}
className={'absolute right-2 ml-2 h-6 cursor-pointer border-none bg-neutral-900 px-2 py-1 text-xs text-neutral-0 transition-colors hover:bg-neutral-700'}>
{'Max'}
</button>
Expand Down
32 changes: 21 additions & 11 deletions apps/common/components/AppHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import Link from 'next/link';
import {useRouter} from 'next/router';
import {AnimatePresence} from 'framer-motion';
import {Popover, Transition} from '@headlessui/react';
import {useIsMounted} from '@react-hookz/web';
import {VaultsHeader} from '@vaults/components/header/VaultsHeader';
import {VeYfiHeader} from '@veYFI/components/header/VeYfiHeader';
import Header from '@yearn-finance/web-lib/components/Header';
Expand All @@ -11,6 +12,7 @@ import {useWeb3} from '@yearn-finance/web-lib/contexts/useWeb3';
import BalanceReminderPopover from '@common/components/BalanceReminderPopover';
import {useMenu} from '@common/contexts/useMenu';
import LogoYearn from '@common/icons/LogoYearn';
import {YBalHeader} from '@yBal/components/header/YBalHeader';
import {YBribeHeader} from '@yBribe/components/header/YBribeHeader';
import {YCrvHeader} from '@yCRV/components/header/YCrvHeader';

Expand All @@ -20,12 +22,13 @@ import {MotionDiv} from './MotionDiv';
import type {ReactElement} from 'react';
import type {TMenu} from '@yearn-finance/web-lib/components/Header';

function Logo(): ReactElement {
const {pathname} = useRouter();
function Logo(): ReactElement {
const {pathname} = useRouter();

return (
<>
<YCrvHeader pathname={pathname} />
<YBalHeader pathname={pathname} />
<VaultsHeader pathname={pathname} />
<VeYfiHeader pathname={pathname} />
<YBribeHeader pathname={pathname} />
Expand All @@ -40,7 +43,7 @@ function Logo(): ReactElement {

}

function LogoPopover(): ReactElement {
function LogoPopover(): ReactElement {
const [isShowing, set_isShowing] = useState(false);

return (
Expand Down Expand Up @@ -94,17 +97,22 @@ function LogoPopover(): ReactElement {
);
}

export function AppHeader(): ReactElement {
const {pathname} = useRouter();
const {isActive} = useWeb3();
const {onOpenMenu} = useMenu();
const menu = useMemo((): TMenu[] => {
export function AppHeader(): ReactElement {
const isMounted = useIsMounted();
const {pathname} = useRouter();
const {isActive} = useWeb3();
const {onOpenMenu} = useMenu();
const menu = useMemo((): TMenu[] => {
const HOME_MENU = {path: '/', label: 'Home'};

if (pathname.startsWith('/ycrv')) {
return [HOME_MENU, ...APPS[AppName.YCRV].menu];
}

if (pathname.startsWith('/ybal')) {
return [HOME_MENU, ...APPS[AppName.YBAL].menu];
}

if (pathname.startsWith('/vaults')) {
return [HOME_MENU, ...APPS[AppName.VAULTS].menu];
}
Expand All @@ -124,8 +132,10 @@ export function AppHeader(): ReactElement {
];
}, [pathname]);

const supportedNetworks = useMemo((): number[] => {
if (pathname.startsWith('/ycrv') || pathname.startsWith('/veyfi') || pathname.startsWith('/ybribe')) {

const supportedNetworks = useMemo((): number[] => {
const ethereumOnlyPaths = ['/ycrv', '/ybal', '/veyfi', '/ybribe'];
if (ethereumOnlyPaths.some((path): boolean => pathname.startsWith(path))) {
return [1];
}

Expand All @@ -145,7 +155,7 @@ export function AppHeader(): ReactElement {
</AnimatePresence>
)}
extra={
<Renderable shouldRender={isActive}>
<Renderable shouldRender={isActive && isMounted()}>
<div className={'ml-4'}>
<BalanceReminderPopover />
</div>
Expand Down
20 changes: 19 additions & 1 deletion apps/common/components/Apps.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import Image from 'next/image';
import vaultsManifest from 'public/apps/vaults-manifest.json';
import veyfiManifest from 'public/apps/veyfi-manifest.json';
import yBalManifest from 'public/apps/ybal-manifest.json';
import ybribeManifest from 'public/apps/ybribe-manifest.json';
import ycrvManifest from 'public/apps/ycrv-manifest.json';
import {VAULTS_MENU} from '@vaults/constants/menu';
import {VEYFI_MENU} from '@veYFI/constants/menu';
import {YCRV_TOKEN_ADDRESS} from '@yearn-finance/web-lib/utils/constants';
import {YBAL_TOKEN_ADDRESS, YCRV_TOKEN_ADDRESS} from '@yearn-finance/web-lib/utils/constants';
import LogoYearn from '@common/icons/LogoYearn';
import {YBAL_MENU} from '@yBal/constants/menu';
import {YBRIBE_MENU} from '@yBribe/constants/menu';
import {YCRV_MENU} from '@yCRV/constants/menu';

Expand All @@ -17,6 +19,7 @@ import type {TMetaFile} from './Meta';
export enum AppName {
VAULTS = 'Vaults',
YCRV = 'yCRV',
YBAL = 'yBal',
VEYFI = 'veYFI',
YBRIBE = 'yBribe'
}
Expand Down Expand Up @@ -55,6 +58,21 @@ export const APPS: { [key in AppName]: TApp } = {
priority />
)
},
yBal: {
name: AppName.YBAL,
href: '/ybal',
menu: YBAL_MENU,
manifest: yBalManifest,
icon: (
<Image
alt={'yBal'}
width={32}
height={32}
src={`${process.env.BASE_YEARN_ASSETS_URI}/1/${YBAL_TOKEN_ADDRESS}/logo-128.png`}
loading={'eager'}
priority />
)
},
veYFI: {
name: AppName.VEYFI,
menu: VEYFI_MENU,
Expand Down
37 changes: 16 additions & 21 deletions apps/common/components/BalanceReminderPopover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {useChainID} from '@yearn-finance/web-lib/hooks/useChainID';
import IconAddToMetamask from '@yearn-finance/web-lib/icons/IconAddToMetamask';
import IconCross from '@yearn-finance/web-lib/icons/IconCross';
import IconWallet from '@yearn-finance/web-lib/icons/IconWallet';
import {toAddress, toWagmiAddress, truncateHex} from '@yearn-finance/web-lib/utils/address';
import {toAddress, truncateHex} from '@yearn-finance/web-lib/utils/address';
import {toBigInt} from '@yearn-finance/web-lib/utils/format.bigNumber';
import {formatAmount} from '@yearn-finance/web-lib/utils/format.number';
import {useWallet} from '@common/contexts/useWallet';
Expand All @@ -26,10 +26,10 @@ type TBalanceReminderElement = {
symbol: string,
}

function TokenItem({element}: {element: TBalanceReminderElement}): ReactElement {
const {provider} = useWeb3();
const {safeChainID} = useChainID();
const balance = useBalance(element.address);
function TokenItem({element}: {element: TBalanceReminderElement}): ReactElement {
const {provider} = useWeb3();
const {safeChainID} = useChainID();
const balance = useBalance(element.address);

async function addTokenToMetamask(address: string, symbol: string, decimals: number, image: string): Promise<void> {
if (!provider) {
Expand All @@ -40,12 +40,7 @@ function TokenItem({element}: {element: TBalanceReminderElement}): ReactElement
const walletClient = await provider.getWalletClient();
await walletClient.watchAsset({
type: 'ERC20',
options: {
address: toWagmiAddress(address),
decimals,
symbol,
image
}
options: {address: toAddress(address), decimals, symbol, image}
});
} catch (error) {
captureException(error);
Expand Down Expand Up @@ -93,12 +88,12 @@ function TokenItem({element}: {element: TBalanceReminderElement}): ReactElement
}

export default function BalanceReminderPopover(): ReactElement {
const {balances, isLoading} = useWallet();
const {address, ens, isActive, onDesactivate} = useWeb3();
const {vaults} = useYearn();
const {balances, isLoading} = useWallet();
const {address, ens, isActive, onDesactivate} = useWeb3();
const {vaults} = useYearn();

const nonNullBalances = useMemo((): TDict<TBalanceData> => {
const nonNullBalances = Object.entries(balances).reduce((acc: TDict<TBalanceData>, [address, balance]): TDict<TBalanceData> => {
const nonNullBalances = useMemo((): TDict<TBalanceData> => {
const nonNullBalances = Object.entries(balances).reduce((acc: TDict<TBalanceData>, [address, balance]): TDict<TBalanceData> => {
if (toBigInt(balance?.raw) > 0n) {
acc[toAddress(address)] = balance;
}
Expand All @@ -107,8 +102,8 @@ export default function BalanceReminderPopover(): ReactElement {
return nonNullBalances;
}, [balances]);

const nonNullBalancesForVault = useMemo((): TBalanceReminderElement[] => {
const nonNullBalancesForVault = Object.entries(nonNullBalances).reduce((acc: TBalanceReminderElement[], [address, balance]): TBalanceReminderElement[] => {
const nonNullBalancesForVault = useMemo((): TBalanceReminderElement[] => {
const nonNullBalancesForVault = Object.entries(nonNullBalances).reduce((acc: TBalanceReminderElement[], [address, balance]): TBalanceReminderElement[] => {
const currentVault = vaults?.[toAddress(address)];
if (currentVault) {
acc.push({
Expand All @@ -123,7 +118,7 @@ export default function BalanceReminderPopover(): ReactElement {
return nonNullBalancesForVault;
}, [nonNullBalances, vaults]);

function renderNoTokenFallback(isLoading: boolean): ReactElement {
function renderNoTokenFallback(isLoading: boolean): ReactElement {
if (isLoading) {
return (
<div className={'py-4 text-center text-sm text-neutral-400'}>
Expand Down Expand Up @@ -153,7 +148,7 @@ export default function BalanceReminderPopover(): ReactElement {
leave={'transition ease-in duration-150'}
leaveFrom={'opacity-100 translate-y-0'}
leaveTo={'opacity-0 translate-y-1'}>
<Popover.Panel className={'yearn--shadow absolute right-0 top-6 z-[1000] mt-3 w-screen max-w-xs md:top-4 md:-right-4'}>
<Popover.Panel className={'yearn--shadow absolute right-0 top-6 z-[1000] mt-3 w-screen max-w-xs md:-right-4 md:top-4'}>
<div className={'overflow-hidden'}>
<div className={'relative bg-neutral-0 p-0'}>
<div className={'flex items-center justify-center border-b border-neutral-300 py-4 text-center'}>
Expand All @@ -165,7 +160,7 @@ export default function BalanceReminderPopover(): ReactElement {
) : 'Connect wallet'}
</b>
</div>
<div className={'absolute top-4 right-4'}>
<div className={'absolute right-4 top-4'}>
<button
onClick={onDesactivate}
className={'flex h-6 w-6 items-center justify-center rounded-full bg-neutral-200/50'}>
Expand Down
2 changes: 1 addition & 1 deletion apps/common/components/HeroTimer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ type TProps = {
endTime?: TSeconds;
}

function HeroTimer({endTime}: TProps): ReactElement {
function HeroTimer({endTime}: TProps): ReactElement {
const time = useTimer({endTime});

return (
Expand Down
21 changes: 11 additions & 10 deletions apps/common/components/ImageWithFallback.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,28 @@
import React, {useState} from 'react';
import Image from 'next/image';
import performBatchedUpdates from '@yearn-finance/web-lib/utils/performBatchedUpdates';

import type {ImageProps} from 'next/image';
import type {ReactElement} from 'react';
import type {CSSProperties, ReactElement} from 'react';

export type TImageWithFallbackProps = ImageProps & {
onCatchError?: () => void;
};
function ImageWithFallback(props: TImageWithFallbackProps): ReactElement {
function ImageWithFallback(props: ImageProps & {onCatchError?: VoidFunction}): ReactElement {
const {alt, src, onCatchError, ...rest} = props;
const [imageSrc, set_imageSrc] = useState(src);
const [imageStyle, set_imageStyle] = useState<CSSProperties>({});

return (
<Image
alt={alt}
src={imageSrc}
loading={'eager'}
style={imageStyle}
onError={(): void => {
set_imageSrc('/placeholder.png');
onCatchError?.();
performBatchedUpdates((): void => {
set_imageSrc('/placeholder.png');
set_imageStyle({filter: 'opacity(0.2)'});
onCatchError?.();
});
}}
{...rest}
/>
{...rest} />
);
}

Expand Down
17 changes: 10 additions & 7 deletions apps/common/components/ListHead.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React, {useCallback} from 'react';
import {cl} from '@yearn-finance/web-lib/utils/cl';
import IconChevronPlain from '@common/icons/IconChevronPlain';

import type {ReactElement} from 'react';
Expand All @@ -12,19 +13,21 @@ export type TListHead = {
className?: string
}[],
dataClassName?: string,
wrapperClassName?: string,
tokenClassName?: string,
sortBy: string,
sortDirection: TSortDirection,
onSort: (sortBy: string, sortDirection: TSortDirection) => void
}

function ListHead({items, dataClassName, sortBy, sortDirection, onSort}: TListHead): ReactElement {
function ListHead({items, dataClassName, wrapperClassName, tokenClassName, sortBy, sortDirection, onSort}: TListHead): ReactElement {
const toggleSortDirection = (newSortBy: string): TSortDirection => {
return sortBy === newSortBy ? (
sortDirection === '' ? 'desc' : sortDirection === 'desc' ? 'asc' : 'desc'
) : 'desc';
};

const renderChevron = useCallback((shouldSortBy: boolean): ReactElement => {
const renderChevron = useCallback((shouldSortBy: boolean): ReactElement => {
if (shouldSortBy && sortDirection === 'desc') {
return <IconChevronPlain className={'yearn--sort-chevron'} />;
}
Expand All @@ -34,11 +37,11 @@ function ListHead({items, dataClassName, sortBy, sortDirection, onSort}: TListHe
return <IconChevronPlain className={'yearn--sort-chevron--off text-neutral-300 group-hover:text-neutral-500'} />;
}, [sortDirection]);

const [first, ...rest] = items;
const [first, ...rest] = items;
return (
<div className={'mt-4 grid w-full grid-cols-1 md:mt-0'}>
<div className={'yearn--table-head-wrapper'}>
<div className={'yearn--table-head-token-section'}>
<div className={cl('yearn--table-head-wrapper', wrapperClassName)}>
<div className={cl('yearn--table-head-token-section', tokenClassName)}>
<button
onClick={(): void => onSort(first.value, toggleSortDirection(first.value))}
className={'yearn--table-head-label-wrapper group'}>
Expand All @@ -49,13 +52,13 @@ function ListHead({items, dataClassName, sortBy, sortDirection, onSort}: TListHe
</button>
</div>

<div className={`yearn--table-head-data-section ${dataClassName || ''}`}>
<div className={cl('yearn--table-head-data-section', dataClassName)}>
{rest.map((item, index): ReactElement => (
<button
key={`${index}_${item.value}`}
onClick={(): void => onSort(item.value, toggleSortDirection(item.value))}
disabled={!item.sortable}
className={`yearn--table-head-label-wrapper group ${item.className}`}
className={cl('yearn--table-head-label-wrapper group', item.className)}
datatype={'number'}>
<p className={'yearn--table-head-label'}>
&nbsp;{item.label}
Expand Down
Loading

0 comments on commit a2a7196

Please sign in to comment.