diff --git a/batcher-ui/components/BatcherInfo/index.tsx b/batcher-ui/components/BatcherInfo/index.tsx index 30798c21..75ecb23c 100644 --- a/batcher-ui/components/BatcherInfo/index.tsx +++ b/batcher-ui/components/BatcherInfo/index.tsx @@ -1,30 +1,24 @@ import React from 'react'; -import { BatcherInfoProps } from '../../utils/types'; import BatcherStepper from '../BatcherStepper'; import { useSelector } from 'react-redux'; import { + batchNumberSelector, batcherStatusSelector, + currentPairSelector, currentSwapSelector, oraclePriceSelector, remainingTimeSelector, + userAddressSelector, userBalancesSelector, } from '../../src/reducers'; import { BatcherStatus } from '../../src/types'; -const BatcherInfo: React.FC = ({ - userAddress, - tokenPair, - buyBalance, - sellBalance, - buyTokenName, - sellTokenName, - openTime, - updateAll, - setUpdateAll, - batchNumber, -}: BatcherInfoProps) => { +const BatcherInfo = () => { const userBalances = useSelector(userBalancesSelector); const currentSwap = useSelector(currentSwapSelector); + const tokenPair = useSelector(currentPairSelector); + const batchNumber = useSelector(batchNumberSelector); + const userAddress = useSelector(userAddressSelector); const status = useSelector(batcherStatusSelector); const remainingTime = useSelector(remainingTimeSelector); @@ -43,18 +37,18 @@ const BatcherInfo: React.FC = ({ )} {status === BatcherStatus.OPEN ? (
-

{remainingTime + ' min'}

+

{`Remaining time : ${remainingTime} min`}

) : (
)} {batchNumber > 0 ? (
-

+

{`${ status === BatcherStatus.CLEARED ? 'LastBatch' - : 'Current batch' + : 'Current batch : ' } ${batchNumber}`}

diff --git a/batcher-ui/components/Exchange/index.tsx b/batcher-ui/components/Exchange/index.tsx index 7f8cbc81..4b823505 100644 --- a/batcher-ui/components/Exchange/index.tsx +++ b/batcher-ui/components/Exchange/index.tsx @@ -2,7 +2,6 @@ import React, { useEffect, useState } from 'react'; import { SwapOutlined } from '@ant-design/icons'; import { message } from 'antd'; import { compose, OpKind, WalletContract } from '@taquito/taquito'; -import { ExchangeProps } from '../../utils/types'; // import { ReactComponent as ExchangeDollarSvg } from '../../../img/exchange-dollar.svg'; import { getErrorMess, getFees, scaleAmountUp } from '../../utils/utils'; import { tzip12 } from '@taquito/tzip12'; @@ -22,12 +21,7 @@ import { useDispatch } from 'react-redux'; import { reverseSwap, updatePriceStrategy } from 'src/actions'; import * as Form from '@radix-ui/react-form'; -const Exchange: React.FC = ({ - buyToken, - sellToken, -}: // updateAll, -// setUpdateAll, -ExchangeProps) => { +const Exchange = () => { const userAddress = useSelector(userAddressSelector); const batcherStatus = useSelector(batcherStatusSelector); const priceStategy = useSelector(priceStrategySelector); diff --git a/batcher-ui/components/Volume/index.tsx b/batcher-ui/components/Volume/index.tsx index 8691f28b..15d1712f 100644 --- a/batcher-ui/components/Volume/index.tsx +++ b/batcher-ui/components/Volume/index.tsx @@ -1,5 +1,4 @@ import React from 'react'; -import { Space, Col, Row, Table } from 'antd'; import { PriceStrategy } from 'src/types'; import { volumesSelector } from 'src/reducers'; import { useSelector } from 'react-redux'; @@ -10,19 +9,6 @@ import { useSelector } from 'react-redux'; const Volume = () => { const { sell, buy } = useSelector(volumesSelector); - console.log('🚀 ~ file: index.tsx:13 ~ Volume ~ sell, buy:', sell, buy); - // const sellVolumes = [ - // { - // sellMinusVolume: volumes.sell_minus_volume, - // sellExactVolume: volumes.sell_exact_volume, - // sellPlusVolume: volumes.sell_plus_volume, - // }, - // ]; - // const buyVolumes = { - // buyMinusVolume: volumes.buy_minus_volume, - // buyExactVolume: volumes.buy_exact_volume, - // buyPlusVolume: volumes.buy_plus_volume, - // }; const listOfBuyVolumesColumns = [ { diff --git a/batcher-ui/pages/_app.tsx b/batcher-ui/pages/_app.tsx index 8197a29a..3457fd94 100644 --- a/batcher-ui/pages/_app.tsx +++ b/batcher-ui/pages/_app.tsx @@ -9,6 +9,7 @@ import { store } from '../src/store'; import NavBar from '../components/NavBar'; import ReactGA from 'react-ga4'; import * as api from '@tzkt/sdk-api'; +import Head from 'next/head'; process.env.NEXT_PUBLIC_GA_TRACKING_ID && ReactGA.initialize(process.env.NEXT_PUBLIC_GA_TRACKING_ID); @@ -24,17 +25,23 @@ const App = ({ Component }: AppProps) => { }, []); return ( - - - -
- - -
-
-
-
-
+
+ + + BATCHER + + + + +
+ + +
+
+
+
+
+
); }; diff --git a/batcher-ui/pages/index.tsx b/batcher-ui/pages/index.tsx index 7d75f59d..1d19342c 100644 --- a/batcher-ui/pages/index.tsx +++ b/batcher-ui/pages/index.tsx @@ -3,22 +3,9 @@ import Exchange from '../components/Exchange'; import Volume from '../components/Volume'; import BatcherInfo from '../components/BatcherInfo'; import BatcherAction from '../components/BatcherAction'; -import { - ContentType, - token, - // BatcherStatus, - Volumes, - // swap, - // tokens, -} from '../utils/types'; +import { ContentType } from '../utils/types'; import { Col, Row } from 'antd'; -import { - getEmptyVolumes, - // setTokenAmount, - // setSocketTokenAmount, - // scaleStringAmountDownToString, -} from '../utils/utils'; // import { // connection as socket, // init_contract, @@ -26,175 +13,32 @@ import { // } from '../utils/webSocketUtils'; // import { scaleAmountUp } from '../utils/utils'; import Holdings from '../components/Holdings'; -import { useTezosToolkit } from '../contexts/tezos-toolkit'; import About from '../components/About'; import { useSelector, useDispatch } from 'react-redux'; import { userAddressSelector } from '../src/reducers'; -import { fetchUserBalances, batcherSetup } from '../src/actions'; +import { + fetchUserBalances, + batcherSetup, + batcherUnsetup, +} from '../src/actions'; const Welcome = () => { - // const tzktUriApi = process.env.NEXT_PUBLIC_TZKT_URI_API; - const batcherContractHash = process.env.NEXT_PUBLIC_BATCHER_CONTRACT_HASH; - const [content, setContent] = useState(ContentType.SWAP); - // const [ tokenMap, setTokenMap] = useState>(new Map()); - // const [ ratesBigMapId , setRatesBigMapId] = useState(0); - // const [userBatchOrderTypesBigMapId, setUserBatchOrderTypesBigMapId] = - // useState(0); - // const [batchesBigMapId, setBatchesBigMapId] = useState(0); - // const chain_api_url = tzktUriApi; - - // const [bigMapsByIdUri] = useState( - // '' + chain_api_url + '/v1/bigmaps/' - // ); const userAddress = useSelector(userAddressSelector); const dispatch = useDispatch(); - const { tezos } = useTezosToolkit(); - - const [buyToken /* setBuyToken */] = useState({ - token_id: 0, - name: 'tzBTC', - address: undefined, - decimals: 8, - standard: 'FA1.2 token', - }); - const [sellToken /* setSellToken */] = useState({ - token_id: 0, - name: 'USDT', - address: undefined, - decimals: 6, - standard: 'FA2 token', - }); - const [tokenPair /* setTokenPair */] = useState( - buyToken.name + '/' + sellToken.name - ); - const [buyBalance /* setBuyBalance */] = useState(0); - const [sellBalance /* setSellBalance */] = useState(0); - - // const [rate, setRate] = useState(0); - // const [status, setStatus] = useState(BatcherStatus.NONE); - const [openTime /* setOpenTime */] = useState(null); const [clearedHoldings, setClearedHoldings] = useState>( new Map() ); const [openHoldings, setOpenHoldings] = useState>( new Map() ); - const [volumes /* setVolumes */] = useState(getEmptyVolumes()); const [updateAll, setUpdateAll] = useState(false); - const [batchNumber /* setBatchNumber */] = useState(0); const [hasClearedHoldings /* setHasClearedHoldings */] = useState(false); - // TODO: typing contract storage - // const pullStorage = async () => { - // if (batcherContractHash) - // return tezos?.contract.getStorage(batcherContractHash); - // return Promise.reject('No contract address'); - // }; - // const scaleVolumeDown = (vols: Volumes) => { - // return { - // buy_minus_volume: scaleStringAmountDownToString( - // vols.buy_minus_volume, - // buyToken.decimals - // ), - // buy_exact_volume: scaleStringAmountDownToString( - // vols.buy_exact_volume, - // buyToken.decimals - // ), - // buy_plus_volume: scaleStringAmountDownToString( - // vols.buy_plus_volume, - // buyToken.decimals - // ), - // sell_minus_volume: scaleStringAmountDownToString( - // vols.sell_minus_volume, - // sellToken.decimals - // ), - // sell_exact_volume: scaleStringAmountDownToString( - // vols.sell_exact_volume, - // sellToken.decimals - // ), - // sell_plus_volume: scaleStringAmountDownToString( - // vols.sell_plus_volume, - // sellToken.decimals - // ), - // }; - // }; - - // const setStatusFromBatch = (sts: string, jsonData: any) => { - // try { - // if (sts === BatcherStatus.OPEN) { - // setOpenTime(jsonData.value.status.open); - // setStatus(BatcherStatus.OPEN); - // } else if (sts === BatcherStatus.CLOSED) { - // setStatus(BatcherStatus.CLOSED); - // } else if (sts === BatcherStatus.CLEARED) { - // setStatus(BatcherStatus.CLEARED); - // } else { - // console.error('Unable to set status', sts); - // } - // } catch (error) { - // console.error('Unable to set status', error); - // } - // }; - // const getCurrentVolume = async (storage: any) => { - // try { - // const currentBatchIndices = storage.batch_set.current_batch_indices; - // const index_map = new Map( - // Object.keys(currentBatchIndices).map(k => [ - // k, - // currentBatchIndices[k] as number, - // ]) - // ); - // const currentBatchNumber = index_map.get(tokenPair) || 0; // TODO: default to 0 ? - // console.log('current_batch_number', currentBatchNumber); - - // if (currentBatchNumber === 0) { - // setBatchNumber(0); - // setStatus(BatcherStatus.NONE); - // const vols: Volumes = getEmptyVolumes(); - // setVolumes(vols); - // } else { - // setBatchNumber(currentBatchNumber); - // const currentBatchURI = - // bigMapsByIdUri + batchesBigMapId + '/keys/' + currentBatchNumber; - // console.log('######Volumes - URI', currentBatchURI); - // const data = await fetch(currentBatchURI, { - // method: 'GET', - // }); - // if (data.ok && data.status !== 204) { - // const jsonData = await data.json(); - // const sts = Object.keys(jsonData.value.status)[0]; - // setStatusFromBatch(sts, jsonData); - // const scaledVolumes = scaleVolumeDown(jsonData.value.volumes); - // setVolumes(scaledVolumes); - // } else { - // console.info('Response from current batch api was no ok', data); - // } - // } - // } catch (error) { - // console.error('Unable to get current volume', error); - // } - // }; - - // const updateSwapMap = async (storage: any) => { - // try { - // const valid_swaps = storage.valid_swaps; - // console.info('Valid Swaps', valid_swaps); - // const swap_map = new Map( - // Object.keys(valid_swaps) - // .filter(k => !valid_swaps[k].is_disabled_for_desposits) - // .map(k => [k, valid_swaps[k]]) - // ); - // setTokenMap(swap_map); - // } catch (error) { - // console.error('Unable to update swap map', error); - // } - // }; - // const getOriginalDepositAmounts = ( // side: any, // initialBuySideAmount: number, @@ -533,10 +377,6 @@ const Welcome = () => { // setHasClearedHoldings(sum_of_holdings > 0); // }; - // const getBatches = async (storage: any) => { - // await getCurrentVolume(storage); - // }; - // const updateTokenBalances = (tokenBalances: any) => { // try { // console.log('tokenbalances', tokenBalances); @@ -555,94 +395,12 @@ const Welcome = () => { // } // }; - // const updateRate = (bigmaps: any) => { - // try { - // console.log('bigmaps', bigmaps); - // const numerator = bigmaps.content.value.rate.p; - // const denominator = bigmaps.content.value.rate.q; - - // const scaledPow = buyToken.decimals - sellToken.decimals; - // const scaledRate = scaleAmountUp(numerator / denominator, scaledPow); - // setRate(scaledRate); - // } catch (error) { - // console.error('Unable to update rate', error); - // } - // }; - - // const updateTokenDetails = async (storage: any) => { - // try { - // setTokenPair(buyToken.name + '/' + sellToken.name); - - // const valid_tokens = storage.valid_tokens; - // const token_map = new Map( - // Object.keys(valid_tokens).map(k => [k, valid_tokens[k]]) - // ); - // const buyTokenData = token_map.get(buyToken.name); - // console.log('buyTokenAddress', buyToken.address); - // const sellTokenData = token_map.get(sellToken.name); - // console.log('sellTokenAddress', sellToken.address); - - // const bToken: token = { - // token_id: buyTokenData.token_id, - // name: buyTokenData.name, - // address: buyTokenData.address, - // decimals: buyTokenData.decimals, - // standard: buyTokenData.standard, - // }; - // const sToken: token = { - // token_id: sellTokenData.token_id, - // name: sellTokenData.name, - // address: sellTokenData.address, - // decimals: sellTokenData.decimals, - // standard: sellTokenData.standard, - // }; - - // if (buyToken != bToken) setBuyToken(bToken); - - // if (sellToken != sToken) setSellToken(sToken); - // } catch (error) { - // console.error('Unable to update token details', error); - // } - // }; - - // const setOraclePrice = async (rates: any[]) => { - // if (rates && rates.length != 0) { - // console.info('rates', rates); - // console.info('tokenPair', tokenPair); - // const rt = rates.filter(r => r.key == tokenPair)[0].value; - // const numerator = rt.rate.p; - // const denominator = rt.rate.q; - - // const scaledPow = buyToken.decimals - sellToken.decimals; - // const scaledRate = scaleAmountUp(numerator / denominator, scaledPow); - // setRate(scaledRate); - // } - // }; - - // const getOraclePrice = async () => { - // //TODO: find a way to get pretty storage - // // const storage = await tezos?.contract.getStorage(batcherContractHash); - // // const rates = storage?.rates_current; - // // console.log('rates ', rates); - // // setOraclePrice(rates?.valueType); - // }; - const renderRightContent = (content: ContentType) => { switch (content) { case ContentType.SWAP: - return ( - - ); + return ; case ContentType.VOLUME: - return ; + return ; case ContentType.REDEEM_HOLDING: return ( { case ContentType.ABOUT: return ; default: - return ( - - ); + return ; } }; - // const updateBigMapIds = (storage: any) => { - // console.log(storage); - // try { - // setRatesBigMapId(storage.rates_current); - // setUserBatchOrderTypesBigMapId(storage.user_batch_ordertypes); - // setBatchesBigMapId(storage.batch_set.batches); - // } catch (error) { - // console.error('Unable to update bigmap ids', error); - // } - // }; - - // const getTokenBalance = async () => { - // try { - // let usrAddr = userAddress; - // if (userAddress === null) { - // if (userAddress !== null) { - // usrAddr = userAddress; - // } - // } - - // if (usrAddr === null) { - // setBuyBalance(0); - // setSellBalance(0); - // } else { - // console.log('getTokenBalance-userAddress', usrAddr); - // const balanceURI = - // tzktUriApi + '/v1/tokens/balances?account=' + usrAddr; - // console.log('getTokenBalance-balanceURI', balanceURI); - - // const buyTokenData = await fetch( - // balanceURI + '&token.contract=' + buyToken.address, - // { - // method: 'GET', - // } - // ); - // const sellTokenData = await fetch( - // balanceURI + '&token.contract=' + sellToken.address, - // { - // method: 'GET', - // } - // ); - - // try { - // await buyTokenData.json().then(balance => { - // if (!buyToken.address) - // throw new Error('address for buyToken is undefined'); - // if (Array.isArray(balance)) { - // setTokenAmount( - // balance, - // buyBalance, - // buyToken.address, - // buyToken.decimals, - // setBuyBalance - // ); - // } - // }); - // } catch (error) { - // console.error(error); - // } - // await sellTokenData.json().then(balance => { - // if (!sellToken.address) - // throw new Error('address for sellToken is undefined'); - // if (Array.isArray(balance)) { - // setTokenAmount( - // balance, - // sellBalance, - // sellToken.address, - // sellToken.decimals, - // setSellBalance - // ); - // } - // }); - // } - // } catch (error) { - // console.error('getTokenBalance-error', error); - // if (!userAddress) { - // setBuyBalance(0); - // setSellBalance(0); - // } else { - // setBuyBalance(-1); - // setSellBalance(-1); - // } - // } - // }; - // const updateFromStorage = async (storage: any) => { // updateBigMapIds(storage); // zeroHoldings(storage, setOpenHoldings, setClearedHoldings); @@ -808,11 +471,6 @@ const Welcome = () => { // }); // }; - // const refreshStorage = async () => { - // console.log('🚀 ~ file: index.tsx:805 ~ refreshStorage ~ refreshStorage:', refreshStorage); - // pullStorage().then((s) => updateFromStorage(s)); - // }; - // useEffect(() => { // console.log('connection', connection); // refreshStorage().then((r) => console.log(r)); @@ -820,63 +478,20 @@ const Welcome = () => { // handleWebsocket(); // }, [connection]); - // useEffect(() => { - // refreshStorage().then((r) => console.log(r)); - // }, [buyToken.address, sellToken.address, updateAll]); - - // useEffect(() => { - // console.log('User address changed - refreshing from storage'); - // refreshStorage().then((r) => console.log(r)); - // init_user(userAddress).then((r) => console.log(r)); - // }, [userAddress]); - useEffect(() => { if (userAddress) dispatch(fetchUserBalances()); }, [userAddress, dispatch]); useEffect(() => { dispatch(batcherSetup()); + return () => { + dispatch(batcherUnsetup()); + }; }, [dispatch]); - useEffect(() => { - if (batcherContractHash) { - // tezos?.contract.getStorage(batcherContractHash).then(b => { - // console.warn(b); - // }) - // CA MARCHE - //fetch('https://api.ghostnet.tzkt.io/v1/bigmaps/321389/keys').then(r => r.json()).then(console.warn) - // CA MARCHE - // contractsGetBigMapByName(batcherContractHash, 'rates_current').then( - // bm => { - // console.warn(bm); - // if (bm.ptr) bigMapsGetKeys(bm.ptr).then(console.warn); - // } - // ); - // tezos?.contract.at(batcherContractHash).then(x => { - // x.storage().then(console.info); - // }); - // contractsGetStorage(batcherContractHash, { path: 'valid_tokens' }).then( - // console.warn - // ); - // getStorageByAddress(batcherContractHash).then(console.info); - // getBatcherStatus(1516, batcherContractHash); - } - }, [batcherContractHash, tezos]); - return (
- +
diff --git a/batcher-ui/public/favicon.ico b/batcher-ui/public/favicon.ico new file mode 100644 index 00000000..4d0f39b0 Binary files /dev/null and b/batcher-ui/public/favicon.ico differ diff --git a/batcher-ui/src/actions/exchange.ts b/batcher-ui/src/actions/exchange.ts index e5c7e058..d3459b30 100644 --- a/batcher-ui/src/actions/exchange.ts +++ b/batcher-ui/src/actions/exchange.ts @@ -70,6 +70,17 @@ export const batcherSetup = () => type: 'BATCHER_SETUP', } as const); +export const batcherTimerId = (timerId: number) => + ({ + type: 'BATCHER_TIMER_ID', + payload: { timerId }, + } as const); + +export const batcherUnsetup = () => + ({ + type: 'BATCHER_UNSETUP', + } as const); + export const getOraclePrice = () => ({ type: 'GET_ORACLE_PRICE', @@ -92,18 +103,20 @@ export const updateVolumes = (volumes: unknown) => payload: { volumes }, } as const); - export type ExchangeActions = - | ReturnType - | ReturnType - | ReturnType - | ReturnType - | ReturnType - | ReturnType - | ReturnType - | ReturnType - | ReturnType - | ReturnType - | ReturnType - | ReturnType - | ReturnType - | ReturnType; +export type ExchangeActions = + | ReturnType + | ReturnType + | ReturnType + | ReturnType + | ReturnType + | ReturnType + | ReturnType + | ReturnType + | ReturnType + | ReturnType + | ReturnType + | ReturnType + | ReturnType + | ReturnType + | ReturnType + | ReturnType; diff --git a/batcher-ui/src/commands/exchange.ts b/batcher-ui/src/commands/exchange.ts index 1855c192..31acb78a 100644 --- a/batcher-ui/src/commands/exchange.ts +++ b/batcher-ui/src/commands/exchange.ts @@ -15,6 +15,7 @@ import { getPairsInfos, updateOraclePrice, updateVolumes, + batcherTimerId, } from '../actions'; import { CurrentSwap } from 'src/types'; @@ -61,7 +62,9 @@ const setupBatcherCmd = (pair: string) => { return Cmd.list([ Cmd.action(getCurrentBatchNumberAction()), Cmd.action(getPairsInfos(pair)), - Cmd.setInterval(Cmd.action(getCurrentBatchNumberAction()), 50000), + Cmd.setInterval(Cmd.action(getCurrentBatchNumberAction()), 50000, { + scheduledActionCreator: timerId => batcherTimerId(timerId), + }), ]); }; diff --git a/batcher-ui/src/reducers/exchange.ts b/batcher-ui/src/reducers/exchange.ts index 11a3c532..c1505fbb 100644 --- a/batcher-ui/src/reducers/exchange.ts +++ b/batcher-ui/src/reducers/exchange.ts @@ -48,6 +48,7 @@ const initialSwap: CurrentSwap = { const initialState: ExchangeState = { priceStrategy: PriceStrategy.EXACT, currentSwap: initialSwap, + batcherTimerId: 0, batcherStatus: { status: BatcherStatus.NONE, at: null, @@ -77,6 +78,10 @@ const exchangeReducer = ( switch (action.type) { case 'BATCHER_SETUP': return loop(state, setupBatcherCmd(state.swapPairName)); + case 'BATCHER_TIMER_ID': + return { ...state, batcherTimerId: action.payload.timerId }; + case 'BATCHER_UNSETUP': + return loop(state, Cmd.clearInterval(state.batcherTimerId)); case 'CHANGE_PAIR': return loop(state, Cmd.action(getPairsInfos(action.payload.pair))); case 'GET_PAIR_INFOS': diff --git a/batcher-ui/src/types/state.ts b/batcher-ui/src/types/state.ts index 5bd5b724..f8b9cc22 100644 --- a/batcher-ui/src/types/state.ts +++ b/batcher-ui/src/types/state.ts @@ -25,6 +25,7 @@ export type ExchangeState = { startTime: string | null; remainingTime: number; }; + batcherTimerId: number; swapPairName: string; batchNumber: number; oraclePrice: number; diff --git a/batcher-ui/utils/types.ts b/batcher-ui/utils/types.ts index 2b1aa6a1..d0a2c85c 100644 --- a/batcher-ui/utils/types.ts +++ b/batcher-ui/utils/types.ts @@ -171,29 +171,6 @@ export type OrderBookProps = { sellToken: token; }; -export type ExchangeProps = { - userAddress: string | undefined; - buyBalance: number; - sellBalance: number; - buyToken: token; - sellToken: token; - updateAll: boolean; - setUpdateAll: (_: boolean) => void; -}; - -export type BatcherInfoProps = { - userAddress: string | undefined; - tokenPair: string; - buyBalance: number; - sellBalance: number; - buyTokenName: string; - sellTokenName: string; - openTime: string | null; - updateAll: boolean; - setUpdateAll: Dispatch>; - batchNumber: number; -}; - export type BatcherActionProps = { content: ContentType; setContent: Dispatch>;