Skip to content

Commit

Permalink
♻️ fix swap pair management to ensure swap is valid
Browse files Browse the repository at this point in the history
  • Loading branch information
Quentin Burg authored and quentin-burg committed Oct 17, 2023
1 parent abb052c commit 44255d2
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 43 deletions.
2 changes: 1 addition & 1 deletion batcher-ui/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const Swap = () => {
return () => {
dispatch(batcherUnsetup());
};
}, [dispatch, tokenPair]);
}, []);

useEffect(() => {
if (userAddress) {
Expand Down
117 changes: 101 additions & 16 deletions batcher-ui/src/components/SelectPair.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { useDispatch } from 'react-redux';
import { changePair } from 'src/actions';
import { getTokensMetadata } from 'src/utils/utils';
import Image from 'next/image';
import { TokenNames } from 'src/types';

interface SelectPairProps {
isFrom: boolean;
Expand All @@ -38,26 +39,114 @@ const SelectPair = ({ isFrom }: SelectPairProps) => {
);
}, []);

const baseToken = ['tzBTC', 'BTCtz'];
const swapsAllowed = [
'tzBTC/USDT',
'tzBTC/EURL',
'BTCtz/USDT',
'BTCtz/USDtz',
'tzBTC/USDtz',
];

const getOtherToken = () => {
if (isReverse && isFrom) return swap.from.token.name;
if (isReverse && !isFrom) return swap.to.name;
if (!isReverse && isFrom) return swap.to.name;
if (!isReverse && !isFrom) return swap.from.token.name;
return swap.to.name;
};

/**
* TODO
* Rewrite this
* @param token TokensNames
* @returns (string | null) A token pair if allowed else null
*/
const choosePair = (
token: TokenNames
): { pair: string; reversed: boolean } | null => {
const other = getOtherToken();
//! Top selector
if (isFrom) {
//! chosen token is a base token
if (baseToken.includes(token)) {
//! user chose the same token so he want to reverse the swap
if (token === other) {
const t = displayValue();
if (swapsAllowed.includes(`${token}/${t}`)) {
return { pair: `${token}/${t}`, reversed: false };
}
return null;
}
//! chosen tokens are in allowed swaps
if (swapsAllowed.includes(`${token}/${other}`)) {
return { pair: `${token}/${other}`, reversed: false };
}
return null;
}
//! chosen token is NOT a base token
if (token === other) {
const t = displayValue();
if (swapsAllowed.includes(`${t}/${token}`)) {
return { pair: `${t}/${token}`, reversed: true };
}
return null;
}
if (swapsAllowed.includes(`${other}/${token}`)) {
return { pair: `${other}/${token}`, reversed: false };
}
return null;
} else {
//! Bottom selector
//! Chosen token is a base token
if (baseToken.includes(token)) {
if (token === other) {
const t = displayValue();
if (swapsAllowed.includes(`${t}/${other}`)) {
return { pair: `${token}/${other}`, reversed: true };
}
return null;
}
//! chosen tokens are in allowed swaps
if (swapsAllowed.includes(`${token}/${other}`)) {
return { pair: `${token}/${other}`, reversed: false };
}
return null;
}
//! chosen token is NOT a base token
if (token === other) {
const t = displayValue();
if (swapsAllowed.includes(`${other}/${t}`)) {
return { pair: `${other}/${t}`, reversed: true };
}
return null;
}
if (swapsAllowed.includes(`${other}/${token}`)) {
return { pair: `${other}/${token}`, reversed: false };
}
return null;
}
};

return (
<Select.Root
value={displayValue()}
onValueChange={value => {
//TODO: change this when we had more pair
const pair =
value === 'tzBTC' ? `tzBTC/${swap.to.name}` : `tzBTC/${value}`;
const reversed =
(!isFrom && value === 'tzBTC') || (isFrom && value !== 'tzBTC');
dispatch(changePair(pair, reversed));
const pairChosen = choosePair(value as TokenNames);
if (!pairChosen) dispatch(changePair('tzBTC/USDT', false));
else {
dispatch(changePair(pairChosen.pair, pairChosen.reversed));
}
}}>
<Select.Trigger className="flex items-center text-dark w-[150px] justify-center rounded px-2 mr-1 text-base gap-2 bg-white hover:bg-hovergray outline-none">
<Select.Trigger className="flex items-center text-dark w-[200px] justify-center rounded px-2 mr-1 text-base gap-2 bg-white hover:bg-hovergray outline-none">
<Select.Value
placeholder={isReverse ? swap.to.name : swap.from.token.name}
/>
<Select.Icon className="text-dark">
<FontAwesomeIcon icon={faChevronDown} />
</Select.Icon>
</Select.Trigger>
<Select.Portal className="w-[7rem]">
<Select.Portal className="w-[8rem]">
<Select.Content className="overflow-hidden bg-white rounded-md text-dark">
<Select.ScrollUpButton className="flex items-center justify-center h-[25px] cursor-default">
<FontAwesomeIcon icon={faChevronUp} />
Expand All @@ -68,11 +157,7 @@ const SelectPair = ({ isFrom }: SelectPairProps) => {
<SelectItem
value={t.name}
key={t.name}
disabled={
isReverse
? swap.to.name === t.name
: swap.from.token.name === t.name
}>
disabled={choosePair(t.name) === null ? true : false}>
<div className="flex items-center">
{t.icon ? (
<Image
Expand Down Expand Up @@ -123,9 +208,9 @@ const SelectItem = React.forwardRef<
disabled={disabled}
className={`${
disabled
? 'data-[highlighted]:cursor-not-allowed data-[highlighted]:bg-white'
: ''
} text-base text-dark rounded flex items-center h-[25px] pr-[35px] pl-[25px] relative select-none data-[highlighted]:outline-none data-[highlighted]:bg-hovergray disabled:cursor-not-allowed`}
? 'cursor-not-allowed bg-lightgray text-white'
: 'cursor-pointer'
} text-base text-dark rounded flex items-center h-[25px] pr-[35px] pl-[25px] relative select-none data-[highlighted]:outline-none data-[highlighted]:bg-hovergray `}
{...props}
ref={forwardedRef}>
<Select.ItemText>{children}</Select.ItemText>
Expand Down
2 changes: 1 addition & 1 deletion batcher-ui/src/config/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ module.exports = {
NEXT_PUBLIC_TZKT_URI_API: 'https://api.ghostnet.tzkt.io',
NEXT_PUBLIC_BATCHER_CONTRACT_HASH: 'KT1LhTpwSGcFAUUM3JYjW8XW74UHP82YzERy',
NEXT_PUBLIC_MARKETMAKER_CONTRACT_HASH:
'KT1XKvKiTTj8N6WKv3MhnZhFjZopFGQGBTdT',
'KT1MHT8jY13A5Sa44mb33HnzBgMX4Sb4FphB',
NEXT_PUBLIC_LOCAL_STORAGE_KEY_STATE: 'batcher-state',
NEXT_PUBLIC_GA_TRACKING_ID: 'G-2K59PEELC8',
},
Expand Down
22 changes: 7 additions & 15 deletions batcher-ui/src/types/contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,13 @@ export enum PriceStrategy {

// ------ BATCHER STORAGE REPRESENTATION ------ //

export type TokenNames = 'tzBTC' | 'EURL' | 'USDT';
export type SwapNames = 'tzBTC/USDT' | 'tzBTC/EURL';
export type TokenNames = 'tzBTC' | 'EURL' | 'USDT' | 'BTCtz' | 'USDtz';
export type SwapNames =
| 'tzBTC/USDT'
| 'tzBTC/EURL'
| 'BTCtz/USDT'
| 'BTCtz/USDtz'
| 'tzBTC/USDtz';

type Swap = {
from: {
Expand Down Expand Up @@ -194,7 +199,6 @@ export type OrderBookBigmap = {

export type BatcherMarketMakerStorage = {
metadata: number; //! ID of metadata bigmap
// valid_tokens: Record<TokenNames, ContractToken>;
valid_tokens: Record<string, ContractToken>;
valid_swaps: Record<
SwapNames,
Expand All @@ -206,20 +210,8 @@ export type BatcherMarketMakerStorage = {
oracle_asset_name: string;
}
>;
// rates_current: number; //! ID of rates_current bigmap
// fee_in_mutez: number;
// batch_set: {
// batches: number; //! ID of batches bigmap
// current_batch_indices: Record<SwapNames, string>; //! Ex: tzBTC/USDT: "300"
// };
administrator: string; //! Address to admin
// fee_recipient: string; //! Address
// last_order_number: string; //! number in string
// user_batch_ordertypes: number; //! ID of order book bigmap
limit_on_tokens_or_pairs: string; //! 10 per default
// deposit_time_window_in_seconds: string; //! 600 at this time
// scale_factor_for_oracle_staleness: string; //! "1"

vault_holdings: number; //! ID of vault_holdings bigmap
vaults: number; //! ID of vaults bigmap
user_holdings: number; //! ID of user_holdings bigmap
Expand Down
10 changes: 1 addition & 9 deletions batcher-ui/src/types/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,19 +70,11 @@ export type UserVault = {
unclaimed: number;
};

// export type MVault = {
// global: GlobalVault;
// user: UserVault;
// };

export type MarketHoldingsState = {
// vaults: Map<string, MVault>;
globalVaults: { [key: string]: GlobalVault };
// globalVaults: Map<string, GlobalVault>;
userVaults: { [key: string]: UserVault };
// userVaults: Map<string, UserVault>;
// current_vault: MVault;
currentVault: string; // token name (EURL, USDT, tzBTC)
currentVault: string; // token name (EURL, USDT, tzBTC, ...)
};

export type EventsState = {
Expand Down
1 change: 0 additions & 1 deletion batcher-ui/src/utils/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -726,7 +726,6 @@ const getUserVault = async (
userVaultId: number,
holdingsVaultId: number
) => {
console.warn('🚀 ~ file: utils.ts:730 ~ userAddress:', userAddress);
if (!userAddress) {
console.error('No user address ');
const userVault: UserVault = {
Expand Down

0 comments on commit 44255d2

Please sign in to comment.