diff --git a/src/components/TradeForm.jsx b/src/components/TradeForm.jsx index 239a47d..83ad2d8 100644 --- a/src/components/TradeForm.jsx +++ b/src/components/TradeForm.jsx @@ -75,10 +75,10 @@ export default function TradeForm({ style, setChangeOrderRef }) { setChangeOrderRef && setChangeOrderRef(doChangeOrder); }, [setChangeOrderRef]); - useEffect(() => { - sizeFraction && onSliderChange(sizeFraction); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [side, sizeFraction]); + // useEffect(() => { + // sizeFraction && onSliderChange(sizeFraction); + // // eslint-disable-next-line react-hooks/exhaustive-deps + // }, [side, sizeFraction]); const doChangeOrder = ({ size, price }) => { size && setSize(size); @@ -203,12 +203,12 @@ export default function TradeForm({ style, setChangeOrderRef }) { step={market?.minOrderSize || 1} onChange={(e) => setSize(e.target.value)} /> - `${value}%`} - marks={sliderMarks} - onChange={onSliderChange} - /> + {/* `${value}%`}*/} + {/* marks={sliderMarks}*/} + {/* onChange={onSliderChange}*/} + {/*/>*/}
{'POST '} { - const id = connection.onSignature( - 'do not worry, this is expected to yield warning logs', - (result) => { - console.log( - 'Received onSignature responses from does-not-exist', - result, - ); - }, - ); - return () => connection.removeSignatureListener(id); - }, [connection]); - useEffect(() => { - const id = sendConnection.onSignature( - 'do not worry, this is expected to yield warning logs', - (result) => { - console.log( - 'Received onSignature responses from does-not-exist', - result, - ); - }, - ); - return () => sendConnection.removeSignatureListener(id); - }, [sendConnection]); + // useEffect(() => { + // const id = connection.onSignature( + // 'do not worry, this is expected to yield warning logs', + // (result) => { + // console.log( + // 'Received onSignature responses from does-not-exist', + // result, + // ); + // }, + // ); + // return () => connection.removeSignatureListener(id); + // }, [connection]); + // useEffect(() => { + // const id = sendConnection.onSignature( + // 'do not worry, this is expected to yield warning logs', + // (result) => { + // console.log( + // 'Received onSignature responses from does-not-exist', + // result, + // ); + // }, + // ); + // return () => sendConnection.removeSignatureListener(id); + // }, [sendConnection]); return ( { if (!publicKey) { return () => {}; } if (accountListenerCount.has(cacheKey)) { - let currentCount = accountListenerCount.get(cacheKey); - accountListenerCount.set(cacheKey, currentCount + 1); - return () => {}; - } - let previousData = null; - const id = connection.onAccountChange(publicKey, (e) => { - if (e.data) { - if (!previousData || !previousData.equals(e.data)) { - setCache(cacheKey, e); + let currentItem = accountListenerCount.get(cacheKey); + console.log('Incrementing', id, currentItem.count + 1); + accountListenerCount.set(cacheKey, { + count: currentItem.count + 1, + subscriptionId: currentItem.subscriptionId, + }); + } else { + let previousData = null; + console.log('Subscribing to ', id); + const subscriptionId = connection.onAccountChange(publicKey, (e) => { + if (e.data) { + if (!previousData || !previousData.equals(e.data)) { + console.log('Passing along new data', id); + setCache(cacheKey, e); + } else { + console.log('Skipping no-op update', id); + } + previousData = e.data; } - previousData = e.data; - } - }); - accountListenerCount.set(cacheKey, 1); + }); + console.log('Setting cache', id); + accountListenerCount.set(cacheKey, { count: 1, subscriptionId }); + } return () => { - let currentCount = accountListenerCount.get(cacheKey); - if (currentCount === 1) { - // last listener, safe to unsubscribe - connection.removeAccountChangeListener(id); + let currentItem = accountListenerCount.get(cacheKey); + let nextCount = currentItem.count - 1; + if (nextCount <= 0) { + console.log('Removing cache', id); + connection.removeAccountChangeListener(currentItem.subscriptionId); accountListenerCount.delete(cacheKey); } else { - accountListenerCount.set(cacheKey, currentCount - 1); + console.log('Decrementing', id, nextCount); + accountListenerCount.set(cacheKey, { + count: nextCount, + subscriptionId: currentItem.subscriptionId, + }); } }; // eslint-disable-next-line react-hooks/exhaustive-deps - }, [connection, publicKey?.toBase58(), cacheKey]); + }, [cacheKey]); return [accountInfo, loaded]; } diff --git a/src/utils/fetch-loop.js b/src/utils/fetch-loop.js index 837c0f8..6954caa 100644 --- a/src/utils/fetch-loop.js +++ b/src/utils/fetch-loop.js @@ -7,10 +7,11 @@ const pageLoadTime = new Date(); const globalCache = new Map(); class FetchLoopListener { - constructor(cacheKey, fn, refreshInterval, callback) { + constructor(cacheKey, fn, refreshInterval, refreshIntervalOnError, callback) { this.cacheKey = cacheKey; this.fn = fn; this.refreshInterval = refreshInterval; + this.refreshIntervalOnError = refreshIntervalOnError; this.callback = callback; } } @@ -30,6 +31,14 @@ class FetchLoopInternal { ); } + get refreshIntervalOnError() { + return Math.min( + ...[...this.listeners] + .map((listener) => listener.refreshIntervalOnError) + .filter((x) => x), + ); + } + get stopped() { return this.listeners.size === 0; } @@ -65,6 +74,7 @@ class FetchLoopInternal { return; } + let errored = false; try { const data = await this.fn(); globalCache.set(this.cacheKey, data); @@ -74,9 +84,17 @@ class FetchLoopInternal { } catch (error) { ++this.errors; console.warn(error); + errored = true; } finally { if (!this.timeoutId && !this.stopped) { let waitTime = this.refreshInterval; + if ( + errored && + this.refreshIntervalOnError && + this.refreshIntervalOnError > 0 + ) { + waitTime = this.refreshIntervalOnError; + } // Back off on errors. if (this.errors > 0) { @@ -141,7 +159,7 @@ const globalLoops = new FetchLoops(); export function useAsyncData( asyncFn, cacheKey, - { refreshInterval = 60000 } = {}, + { refreshInterval = 60000, refreshIntervalOnError = null } = {}, ) { const [, rerender] = useReducer((i) => i + 1, 0); @@ -154,6 +172,7 @@ export function useAsyncData( cacheKey, asyncFn, refreshInterval, + refreshIntervalOnError, rerender, ); globalLoops.addListener(listener); diff --git a/src/utils/markets.js b/src/utils/markets.js index b7dfc21..be5fd77 100644 --- a/src/utils/markets.js +++ b/src/utils/markets.js @@ -131,12 +131,12 @@ export function useAllMarkets() { const MarketContext = React.createContext(null); // For things that don't really change -const _SLOW_REFRESH_INTERVAL = 1000 * 1000; +const _SLOW_REFRESH_INTERVAL = 5 * 1000; // For things that change frequently -const _FAST_REFRESH_INTERVAL = 5 * 1000; +const _FAST_REFRESH_INTERVAL = 1000; -const _MEDIUM_REFRESH_INTERVAL = 5 * 1000; +const _MEDIUM_REFRESH_INTERVAL = 3 * 1000; export function MarketProvider({ children }) { const [marketName, setMarketName] = useLocalStorageState( @@ -601,9 +601,12 @@ export function useBalances() { openOrdersAccount && openOrdersAccount.quoteTokenTotal && openOrdersAccount.quoteTokenFree; + if (baseCurrency === 'UNKNOWN' || quoteCurrency === 'UNKNOWN') { + return []; + } return [ { - key: baseCurrency, + key: `${baseCurrency}${quoteCurrency}${baseCurrency}`, coin: baseCurrency, wallet: baseCurrencyBalances, orders: @@ -620,7 +623,7 @@ export function useBalances() { : null, }, { - key: quoteCurrency, + key: `${quoteCurrency}${baseCurrency}${quoteCurrency}`, coin: quoteCurrency, wallet: quoteCurrencyBalances, orders: diff --git a/src/utils/send.js b/src/utils/send.js index 1546099..eee4ba0 100644 --- a/src/utils/send.js +++ b/src/utils/send.js @@ -19,7 +19,17 @@ export async function settleFunds({ !baseCurrencyAccount || !quoteCurrencyAccount ) { - notify({ message: 'Not connected' }); + if ( + (baseCurrencyAccount && !quoteCurrencyAccount) || + (quoteCurrencyAccount && !baseCurrencyAccount) + ) { + notify({ + message: 'Add token account', + description: 'Add accounts for both currencies on sollet.io', + }); + } else { + notify({ message: 'Not connected' }); + } return; } const transaction = await market.makeSettleFundsTransaction(