Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable Forex AMM on Pendulum #569

Merged
merged 11 commits into from
Oct 9, 2024
6 changes: 2 additions & 4 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -1,4 +1,2 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

npx lint-staged
# .husky/pre-commit
yarn lint-staged
16 changes: 12 additions & 4 deletions src/components/nabla/Pools/Swap/columns.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { CellContext, ColumnDef } from '@tanstack/react-table';
import { Badge, Button } from 'react-daisyui';
import { Avatar, Badge, Button } from 'react-daisyui';
import Big from 'big.js';
import { useModalToggle } from '../../../../services/modal';
import { rawToDecimal } from '../../../../shared/parseNumbers/metric';
import { NablaInstanceBackstopPool, NablaInstanceSwapPool } from '../../../../hooks/nabla/useNablaInstance';
import { swapPoolAbi } from '../../../../contracts/nabla/SwapPool';
import { getIcon } from '../../../../shared/AssetIcons';
import { Erc20Balance } from '../../common/Erc20Balance';
import { LiquidityModalProps } from './SwapPoolModals';
import Big from 'big.js';

export type SwapPoolColumn = NablaInstanceSwapPool & {
backstopPool: NablaInstanceBackstopPool;
Expand All @@ -17,7 +18,14 @@ const BIG_100 = new Big(100);
export const nameColumn: ColumnDef<SwapPoolColumn> = {
header: 'Name',
accessorKey: 'name',
accessorFn: (row) => row.token?.name || '',
accessorFn: (row) => row.token.name,
cell: ({ row: { original } }) =>
(
<div className="flex items-center">
<Avatar src={getIcon(original.token.symbol)} shape="circle" size={32} />
<p className="ml-2.5">{original.token.name}</p>
</div>
) || '',
enableSorting: true,
} as const;

Expand Down Expand Up @@ -46,7 +54,7 @@ export const aprColumn: ColumnDef<SwapPoolColumn> = {
accessorKey: 'apr',
accessorFn: (row) => rawToDecimal(row.apr, row.token.decimals).mul(BIG_100).toFixed(2, 0),
cell: (props): JSX.Element | null => (
<Badge className="h-auto rounded-lg bg-success/35 px-2 py-1 text-blackAlpha-700 dark:text-white">
<Badge className="h-auto px-2 py-1 rounded-lg bg-success/35 text-blackAlpha-700 dark:text-white">
{props.renderValue()}%
</Badge>
),
Expand Down
38 changes: 25 additions & 13 deletions src/components/nabla/Swap/From.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { FieldPath, FieldValues, UseFormReturn, useFormContext } from 'react-hook-form';
import { ChevronDownIcon } from '@heroicons/react/20/solid';
import { Button } from 'react-daisyui';
import { FieldPath, FieldValues, UseFormReturn, useFormContext } from 'react-hook-form';
import Big from 'big.js';

import { NablaTokenPrice } from '../common/NablaTokenPrice';
import { fractionOfValue } from '../../../shared/parseNumbers/metric';
Expand All @@ -14,21 +15,23 @@ import { useGlobalState } from '../../../GlobalStateProvider';
import { SwapFormValues } from './schema';

interface FromProps<FormFieldValues extends FieldValues, TFieldName extends FieldPath<FormFieldValues>> {
fromToken: NablaInstanceToken | undefined;
onOpenSelector: () => void;
inputHasError: boolean;
fromFormFieldName: TFieldName;
form: UseFormReturn<FormFieldValues>;
fromTokenBalance: UseContractReadResult<ContractBalance | undefined>;
fromToken?: NablaInstanceToken;
fromAmount?: Big;
fromFormFieldName: TFieldName;
onOpenSelector: () => void;
inputHasError: boolean;
}

export function From<FormFieldValues extends FieldValues, TFieldName extends FieldPath<FormFieldValues>>({
form,
fromToken,
fromAmount,
fromTokenBalance,
fromFormFieldName,
onOpenSelector,
inputHasError,
fromFormFieldName,
form,
fromTokenBalance,
}: FromProps<FormFieldValues, TFieldName>) {
const { setValue } = useFormContext<SwapFormValues>();

Expand All @@ -38,7 +41,7 @@ export function From<FormFieldValues extends FieldValues, TFieldName extends Fie
<div
className={`rounded-lg border bg-base-300 px-4 py-3 ${inputHasError ? 'border-red-600' : 'border-transparent'}`}
>
<div className="flex w-full justify-between">
<div className="flex justify-between w-full">
<div className="font-outfit flex-grow text-4xl text-[inherit]">
<AmountSelector
maxBalance={fromTokenBalance.data}
Expand All @@ -54,15 +57,24 @@ export function From<FormFieldValues extends FieldValues, TFieldName extends Fie
type="button"
>
<span className="mr-1 h-full rounded-full bg-[rgba(0,0,0,0.15)] p-px">
<img src={getIcon(fromToken?.symbol)} alt={fromToken?.name} className="h-full w-auto" />
<img src={getIcon(fromToken?.symbol)} alt={fromToken?.name} className="w-auto h-full" />
</span>
<strong className="font-bold">{fromToken?.symbol || 'Select'}</strong>
<ChevronDownIcon className="ml-px inline h-4 w-4" />
<ChevronDownIcon className="inline w-4 h-4 ml-px" />
</Button>
</div>
<div className="mt-1 flex items-center justify-between text-neutral-500 dark:text-neutral-400">
<div className="flex items-center justify-between mt-1 text-neutral-500 dark:text-neutral-400">
<div className="mt-px text-sm">
{fromToken ? <NablaTokenPrice address={fromToken.id} fallback="$ -" /> : '$ -'}
{fromToken ? (
<NablaTokenPrice
formatByAmount={true}
currentTokenAmount={fromAmount}
address={fromToken.id}
fallback="$ -"
/>
) : (
'$ -'
)}
</div>
<div className="flex gap-1 text-sm">
{fromTokenBalance !== undefined && walletAccount && (
Expand Down
31 changes: 21 additions & 10 deletions src/components/nabla/Swap/To.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,24 @@ import { useFormContext } from 'react-hook-form';
import Big from 'big.js';

import { UseTokenOutAmountResult } from '../../../hooks/nabla/useTokenOutAmount';
import useBoolean from '../../../hooks/useBoolean';
import { NumberLoader } from '../../Loader';
import { Skeleton } from '../../Skeleton';
import { SwapFormValues } from './schema';
import { NablaInstanceToken } from '../../../hooks/nabla/useNablaInstance';
import useBoolean from '../../../hooks/useBoolean';
import { erc20WrapperAbi } from '../../../contracts/nabla/ERC20Wrapper';
import { NablaTokenPrice } from '../common/NablaTokenPrice';
import { Erc20Balance } from '../common/Erc20Balance';
import { getIcon } from '../../../shared/AssetIcons';
import { useGlobalState } from '../../../GlobalStateProvider';
import { NumberLoader } from '../../Loader';
import { Skeleton } from '../../Skeleton';
import { SwapFormValues } from './schema';

export interface ToProps {
onOpenSelector: () => void;
fromToken: NablaInstanceToken | undefined;
toToken: NablaInstanceToken | undefined;
fromToken?: NablaInstanceToken;
fromAmount?: Big;
toToken?: NablaInstanceToken;
toAmountQuote: UseTokenOutAmountResult;
fromAmount: Big | undefined;
slippage: number;
onOpenSelector: () => void;
}

export function To({
Expand Down Expand Up @@ -81,7 +81,18 @@ export function To({
</Button>
</div>
<div className="mt-1 flex items-center justify-between text-neutral-500 dark:text-neutral-300">
<div className="mt-px text-sm">{toToken ? <NablaTokenPrice address={toToken.id} fallback="$ -" /> : '$ -'}</div>
<div className="mt-px text-sm">
{toToken ? (
<NablaTokenPrice
formatByAmount={true}
currentTokenAmount={Big(toAmountQuote.data?.amountOut.approximateStrings.atLeast4Decimals ?? 0)}
address={toToken.id}
fallback="$ -"
/>
) : (
'$ -'
)}
</div>
{walletAccount && (
<div className="flex gap-1 text-sm">
Balance:{' '}
Expand All @@ -96,7 +107,7 @@ export function To({
</div>
<div className="-mx-4 mt-4 h-px bg-[rgba(0,0,0,0.15)]" />
<div
className={`collapse -mx-4 overflow-visible text-neutral-500 dark:text-neutral-300 text-sm${
className={`collapse -mx-4 overflow-visible text-sm text-neutral-500 dark:text-neutral-300 ${
isOpen ? 'collapse-open' : ''
}`}
>
Expand Down
11 changes: 6 additions & 5 deletions src/components/nabla/Swap/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,26 +77,27 @@ const Swap = (props: UseSwapComponentProps): JSX.Element | null => {
/>
</div>
<From
fromToken={fromToken}
onOpenSelector={() => setModalType('from')}
inputHasError={inputHasErrors}
form={form}
fromToken={fromToken}
fromAmount={fromAmount}
fromFormFieldName="fromAmount"
fromTokenBalance={fromTokenBalance}
onOpenSelector={() => setModalType('from')}
inputHasError={inputHasErrors}
/>
<SwapAssetsButton
onClick={() => {
toToken && onFromChange(toToken.id);
}}
/>
<To
toToken={toToken}
fromToken={fromToken}
fromAmount={fromAmount}
toToken={toToken}
toAmountQuote={
inputHasErrors ? { enabled: false, data: undefined, error: null, isLoading: false } : toAmountQuote
}
onOpenSelector={() => setModalType('to')}
fromAmount={fromAmount}
slippage={slippage}
/>
<Validation className="mb-2 text-center" errors={errors} />
Expand Down
11 changes: 8 additions & 3 deletions src/components/nabla/common/NablaFootnote.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
const nablaHomepageUrl = 'https://nabla.fi';
const nablaHomepageUrl = 'https://vortexfinance.co';

export function NablaFootnote() {
return (
<div className="mt-3 text-center text-sm font-bold">
<div className="mt-3 text-sm font-bold text-center">
Powered by{' '}
<a href={nablaHomepageUrl} target="_blank" rel="noreferrer">
<a
href={nablaHomepageUrl}
target="_blank"
rel="noreferrer"
className="transition hover:text-primary hover:underline"
>
Vortex Finance
</a>
</div>
Expand Down
23 changes: 21 additions & 2 deletions src/components/nabla/common/NablaTokenPrice.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,37 @@
import { NumberLoader } from '../../Loader';
import Big from 'big.js';
import { useNablaTokenPrice } from '../../../hooks/nabla/useNablaTokenPrice';
import { NumberLoader } from '../../Loader';

export type TokenPriceProps = {
address: string;
prefix?: ReactNode;
fallback?: ReactNode;
currentTokenAmount?: Big;
formatByAmount?: boolean;
};

export function NablaTokenPrice({ address, prefix = null, fallback = null }: TokenPriceProps): JSX.Element | null {
export function NablaTokenPrice({
address,
prefix = null,
fallback = null,
formatByAmount = false,
currentTokenAmount = Big(0),
}: TokenPriceProps): JSX.Element | null {
const { data, isLoading } = useNablaTokenPrice(address);
if (isLoading) return <NumberLoader />;

if (data === undefined) return fallback;

if (formatByAmount) {
const currentAmountPrice = Big(data.approximateStrings.atLeast2Decimals).mul(currentTokenAmount).toFixed(2, 0);

return (
<span>
{prefix}${currentAmountPrice}
</span>
);
}

return (
<span>
{prefix}${data.approximateStrings.atLeast2Decimals}
Expand Down
9 changes: 7 additions & 2 deletions src/config/apps/nabla.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,16 @@ export type NablaConfig = AppConfigBase &
>;

export const nablaConfig: NablaConfig = {
tenants: [TenantName.Foucoco],
environment: ['staging', 'development'],
tenants: [TenantName.Foucoco, TenantName.Pendulum],
environment: ['staging', 'development', 'production'],
foucoco: {
indexerUrl: 'https://pendulum.squids.live/foucoco-squid/graphql',
router: '6h3UHXZonhJthkrchJYiwgBc8CPeNuZYscWUVPFzTAeDGKt9',
oracle: '6hGZBCyk3adNg1kVs2cdB9bKC4L1e4WersuWextDGbKWLngE',
},
pendulum: {
indexerUrl: 'https://pendulum.squids.live/pendulum-squid/graphql',
router: '6fEJAs1ycfTNDZY7ZoAtkBhuhHnRVNscdALMBLdjDV12K4uE',
oracle: '6fxpVAp3W5mJsXqnBiQresTd8HZDkNMRFCafbXC9X2AAjFHY',
},
};
Loading