websocket, polling rate, and component updates
This commit is contained in:
parent
c79765dd33
commit
c5d8fef7d6
|
@ -75,10 +75,10 @@ export default function TradeForm({ style, setChangeOrderRef }) {
|
||||||
setChangeOrderRef && setChangeOrderRef(doChangeOrder);
|
setChangeOrderRef && setChangeOrderRef(doChangeOrder);
|
||||||
}, [setChangeOrderRef]);
|
}, [setChangeOrderRef]);
|
||||||
|
|
||||||
useEffect(() => {
|
// useEffect(() => {
|
||||||
sizeFraction && onSliderChange(sizeFraction);
|
// sizeFraction && onSliderChange(sizeFraction);
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// // eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [side, sizeFraction]);
|
// }, [side, sizeFraction]);
|
||||||
|
|
||||||
const doChangeOrder = ({ size, price }) => {
|
const doChangeOrder = ({ size, price }) => {
|
||||||
size && setSize(size);
|
size && setSize(size);
|
||||||
|
@ -203,12 +203,12 @@ export default function TradeForm({ style, setChangeOrderRef }) {
|
||||||
step={market?.minOrderSize || 1}
|
step={market?.minOrderSize || 1}
|
||||||
onChange={(e) => setSize(e.target.value)}
|
onChange={(e) => setSize(e.target.value)}
|
||||||
/>
|
/>
|
||||||
<Slider
|
{/*<Slider*/}
|
||||||
value={sizeFraction}
|
{/* value={sizeFraction}*/}
|
||||||
tipFormatter={(value) => `${value}%`}
|
{/* tipFormatter={(value) => `${value}%`}*/}
|
||||||
marks={sliderMarks}
|
{/* marks={sliderMarks}*/}
|
||||||
onChange={onSliderChange}
|
{/* onChange={onSliderChange}*/}
|
||||||
/>
|
{/*/>*/}
|
||||||
<div style={{ paddingTop: 18 }}>
|
<div style={{ paddingTop: 18 }}>
|
||||||
{'POST '}
|
{'POST '}
|
||||||
<Switch
|
<Switch
|
||||||
|
|
|
@ -34,30 +34,30 @@ export function ConnectionProvider({ children }) {
|
||||||
// The websocket library solana/web3.js uses closes its websocket connection when the subscription list
|
// The websocket library solana/web3.js uses closes its websocket connection when the subscription list
|
||||||
// is empty after opening its first time, preventing subsequent subscriptions from receiving responses.
|
// is empty after opening its first time, preventing subsequent subscriptions from receiving responses.
|
||||||
// This is a hack to prevent the list from every getting empty
|
// This is a hack to prevent the list from every getting empty
|
||||||
useEffect(() => {
|
// useEffect(() => {
|
||||||
const id = connection.onSignature(
|
// const id = connection.onSignature(
|
||||||
'do not worry, this is expected to yield warning logs',
|
// 'do not worry, this is expected to yield warning logs',
|
||||||
(result) => {
|
// (result) => {
|
||||||
console.log(
|
// console.log(
|
||||||
'Received onSignature responses from does-not-exist',
|
// 'Received onSignature responses from does-not-exist',
|
||||||
result,
|
// result,
|
||||||
);
|
// );
|
||||||
},
|
// },
|
||||||
);
|
// );
|
||||||
return () => connection.removeSignatureListener(id);
|
// return () => connection.removeSignatureListener(id);
|
||||||
}, [connection]);
|
// }, [connection]);
|
||||||
useEffect(() => {
|
// useEffect(() => {
|
||||||
const id = sendConnection.onSignature(
|
// const id = sendConnection.onSignature(
|
||||||
'do not worry, this is expected to yield warning logs',
|
// 'do not worry, this is expected to yield warning logs',
|
||||||
(result) => {
|
// (result) => {
|
||||||
console.log(
|
// console.log(
|
||||||
'Received onSignature responses from does-not-exist',
|
// 'Received onSignature responses from does-not-exist',
|
||||||
result,
|
// result,
|
||||||
);
|
// );
|
||||||
},
|
// },
|
||||||
);
|
// );
|
||||||
return () => sendConnection.removeSignatureListener(id);
|
// return () => sendConnection.removeSignatureListener(id);
|
||||||
}, [sendConnection]);
|
// }, [sendConnection]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ConnectionContext.Provider
|
<ConnectionContext.Provider
|
||||||
|
@ -89,37 +89,52 @@ export function useAccountInfo(publicKey) {
|
||||||
cacheKey,
|
cacheKey,
|
||||||
{ refreshInterval: 60000000 },
|
{ refreshInterval: 60000000 },
|
||||||
);
|
);
|
||||||
|
let id = publicKey?.toBase58();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!publicKey) {
|
if (!publicKey) {
|
||||||
return () => {};
|
return () => {};
|
||||||
}
|
}
|
||||||
if (accountListenerCount.has(cacheKey)) {
|
if (accountListenerCount.has(cacheKey)) {
|
||||||
let currentCount = accountListenerCount.get(cacheKey);
|
let currentItem = accountListenerCount.get(cacheKey);
|
||||||
accountListenerCount.set(cacheKey, currentCount + 1);
|
console.log('Incrementing', id, currentItem.count + 1);
|
||||||
return () => {};
|
accountListenerCount.set(cacheKey, {
|
||||||
}
|
count: currentItem.count + 1,
|
||||||
let previousData = null;
|
subscriptionId: currentItem.subscriptionId,
|
||||||
const id = connection.onAccountChange(publicKey, (e) => {
|
});
|
||||||
if (e.data) {
|
} else {
|
||||||
if (!previousData || !previousData.equals(e.data)) {
|
let previousData = null;
|
||||||
setCache(cacheKey, e);
|
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;
|
});
|
||||||
}
|
console.log('Setting cache', id);
|
||||||
});
|
accountListenerCount.set(cacheKey, { count: 1, subscriptionId });
|
||||||
accountListenerCount.set(cacheKey, 1);
|
}
|
||||||
return () => {
|
return () => {
|
||||||
let currentCount = accountListenerCount.get(cacheKey);
|
let currentItem = accountListenerCount.get(cacheKey);
|
||||||
if (currentCount === 1) {
|
let nextCount = currentItem.count - 1;
|
||||||
// last listener, safe to unsubscribe
|
if (nextCount <= 0) {
|
||||||
connection.removeAccountChangeListener(id);
|
console.log('Removing cache', id);
|
||||||
|
connection.removeAccountChangeListener(currentItem.subscriptionId);
|
||||||
accountListenerCount.delete(cacheKey);
|
accountListenerCount.delete(cacheKey);
|
||||||
} else {
|
} 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
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [connection, publicKey?.toBase58(), cacheKey]);
|
}, [cacheKey]);
|
||||||
return [accountInfo, loaded];
|
return [accountInfo, loaded];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,10 +7,11 @@ const pageLoadTime = new Date();
|
||||||
const globalCache = new Map();
|
const globalCache = new Map();
|
||||||
|
|
||||||
class FetchLoopListener {
|
class FetchLoopListener {
|
||||||
constructor(cacheKey, fn, refreshInterval, callback) {
|
constructor(cacheKey, fn, refreshInterval, refreshIntervalOnError, callback) {
|
||||||
this.cacheKey = cacheKey;
|
this.cacheKey = cacheKey;
|
||||||
this.fn = fn;
|
this.fn = fn;
|
||||||
this.refreshInterval = refreshInterval;
|
this.refreshInterval = refreshInterval;
|
||||||
|
this.refreshIntervalOnError = refreshIntervalOnError;
|
||||||
this.callback = callback;
|
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() {
|
get stopped() {
|
||||||
return this.listeners.size === 0;
|
return this.listeners.size === 0;
|
||||||
}
|
}
|
||||||
|
@ -65,6 +74,7 @@ class FetchLoopInternal {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let errored = false;
|
||||||
try {
|
try {
|
||||||
const data = await this.fn();
|
const data = await this.fn();
|
||||||
globalCache.set(this.cacheKey, data);
|
globalCache.set(this.cacheKey, data);
|
||||||
|
@ -74,9 +84,17 @@ class FetchLoopInternal {
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
++this.errors;
|
++this.errors;
|
||||||
console.warn(error);
|
console.warn(error);
|
||||||
|
errored = true;
|
||||||
} finally {
|
} finally {
|
||||||
if (!this.timeoutId && !this.stopped) {
|
if (!this.timeoutId && !this.stopped) {
|
||||||
let waitTime = this.refreshInterval;
|
let waitTime = this.refreshInterval;
|
||||||
|
if (
|
||||||
|
errored &&
|
||||||
|
this.refreshIntervalOnError &&
|
||||||
|
this.refreshIntervalOnError > 0
|
||||||
|
) {
|
||||||
|
waitTime = this.refreshIntervalOnError;
|
||||||
|
}
|
||||||
|
|
||||||
// Back off on errors.
|
// Back off on errors.
|
||||||
if (this.errors > 0) {
|
if (this.errors > 0) {
|
||||||
|
@ -141,7 +159,7 @@ const globalLoops = new FetchLoops();
|
||||||
export function useAsyncData(
|
export function useAsyncData(
|
||||||
asyncFn,
|
asyncFn,
|
||||||
cacheKey,
|
cacheKey,
|
||||||
{ refreshInterval = 60000 } = {},
|
{ refreshInterval = 60000, refreshIntervalOnError = null } = {},
|
||||||
) {
|
) {
|
||||||
const [, rerender] = useReducer((i) => i + 1, 0);
|
const [, rerender] = useReducer((i) => i + 1, 0);
|
||||||
|
|
||||||
|
@ -154,6 +172,7 @@ export function useAsyncData(
|
||||||
cacheKey,
|
cacheKey,
|
||||||
asyncFn,
|
asyncFn,
|
||||||
refreshInterval,
|
refreshInterval,
|
||||||
|
refreshIntervalOnError,
|
||||||
rerender,
|
rerender,
|
||||||
);
|
);
|
||||||
globalLoops.addListener(listener);
|
globalLoops.addListener(listener);
|
||||||
|
|
|
@ -131,12 +131,12 @@ export function useAllMarkets() {
|
||||||
const MarketContext = React.createContext(null);
|
const MarketContext = React.createContext(null);
|
||||||
|
|
||||||
// For things that don't really change
|
// For things that don't really change
|
||||||
const _SLOW_REFRESH_INTERVAL = 1000 * 1000;
|
const _SLOW_REFRESH_INTERVAL = 5 * 1000;
|
||||||
|
|
||||||
// For things that change frequently
|
// 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 }) {
|
export function MarketProvider({ children }) {
|
||||||
const [marketName, setMarketName] = useLocalStorageState(
|
const [marketName, setMarketName] = useLocalStorageState(
|
||||||
|
@ -601,9 +601,12 @@ export function useBalances() {
|
||||||
openOrdersAccount &&
|
openOrdersAccount &&
|
||||||
openOrdersAccount.quoteTokenTotal &&
|
openOrdersAccount.quoteTokenTotal &&
|
||||||
openOrdersAccount.quoteTokenFree;
|
openOrdersAccount.quoteTokenFree;
|
||||||
|
if (baseCurrency === 'UNKNOWN' || quoteCurrency === 'UNKNOWN') {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
key: baseCurrency,
|
key: `${baseCurrency}${quoteCurrency}${baseCurrency}`,
|
||||||
coin: baseCurrency,
|
coin: baseCurrency,
|
||||||
wallet: baseCurrencyBalances,
|
wallet: baseCurrencyBalances,
|
||||||
orders:
|
orders:
|
||||||
|
@ -620,7 +623,7 @@ export function useBalances() {
|
||||||
: null,
|
: null,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: quoteCurrency,
|
key: `${quoteCurrency}${baseCurrency}${quoteCurrency}`,
|
||||||
coin: quoteCurrency,
|
coin: quoteCurrency,
|
||||||
wallet: quoteCurrencyBalances,
|
wallet: quoteCurrencyBalances,
|
||||||
orders:
|
orders:
|
||||||
|
|
|
@ -19,7 +19,17 @@ export async function settleFunds({
|
||||||
!baseCurrencyAccount ||
|
!baseCurrencyAccount ||
|
||||||
!quoteCurrencyAccount
|
!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;
|
return;
|
||||||
}
|
}
|
||||||
const transaction = await market.makeSettleFundsTransaction(
|
const transaction = await market.makeSettleFundsTransaction(
|
||||||
|
|
Loading…
Reference in New Issue