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

[web] Make APIs work again #317

Closed
wants to merge 20 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
547d2e3
Merge pull request #290 from inevitable-changes/develop
junhoyeo Oct 10, 2022
d2d547e
Merge pull request #293 from inevitable-changes/develop
junhoyeo Oct 10, 2022
752502f
Merge pull request #295 from inevitable-changes/develop
junhoyeo Oct 10, 2022
4512386
Merge pull request #300 from inevitable-changes/develop
junhoyeo Oct 10, 2022
b627170
Merge pull request #304 from inevitable-changes/develop
junhoyeo Oct 11, 2022
1bfdea6
Merge pull request #314 from inevitable-changes/develop
junhoyeo Oct 12, 2022
ae55c46
Merge pull request #316 from inevitable-changes/develop
junhoyeo Oct 12, 2022
b556a9a
[web/hotfix] Use deprecated `safePromiseAllV1`
junhoyeo Oct 12, 2022
3cb7c95
Merge branch 'main' of https://github.com/inevitable-changes/bento in…
junhoyeo Oct 12, 2022
4f6baa9
Revert "Merge pull request #314 from inevitable-changes/develop"
junhoyeo Oct 12, 2022
d53a9c4
[web] Show logo and description for Klaytn DeFis (#305)
junhoyeo Oct 11, 2022
57cabee
[web] Fix `withoutEmptyDeFiStaking` to check wallet LPs (#306)
junhoyeo Oct 11, 2022
a551574
[web] Trigger force re-render on request state changes in `useMultipl…
junhoyeo Oct 11, 2022
6e8cbcd
[web] Show valuation for DeFi protocols in dashboard (#308)
junhoyeo Oct 11, 2022
8377993
[web] Include `tokenAmounts` in KLAYswap single staking (#313)
junhoyeo Oct 12, 2022
8797cd3
[web] Show DeFi net worth by staking/location & Add Korean translatio…
junhoyeo Oct 12, 2022
acd1985
[web] Use `reduce` in `safePromiseAll` to make it work for 2D arrays …
junhoyeo Oct 11, 2022
660b4f0
[web/hotfix] Respond to `safePromiseAll` changes in API (#315)
junhoyeo Oct 12, 2022
6c8bdb5
[web] Cache/Manage pricings using global context (#310)
junhoyeo Oct 12, 2022
a1576d5
Use `useClientCallback` to make callbacks only in client
junhoyeo Oct 12, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions packages/bento-core/chains/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Config, safePromiseAllV1 } from '@bento/common';
import { Config, safePromiseAll } from '@bento/common';
import { JsonRpcProvider } from '@ethersproject/providers';
import * as web3 from '@solana/web3.js';
import axios, { Axios } from 'axios';
Expand Down Expand Up @@ -95,7 +95,7 @@ export class EthereumChain implements Chain {
price,
};
}) as Promise<TokenBalance>[];
return safePromiseAllV1(promises);
return safePromiseAll(promises).then((items) => items.flat());
};
}

Expand Down Expand Up @@ -170,7 +170,7 @@ export class BNBChain implements Chain {
price,
};
}) as Promise<TokenBalance>[];
return safePromiseAllV1(promises);
return safePromiseAll(promises).then((items) => items.flat());
};
}

Expand Down Expand Up @@ -245,7 +245,7 @@ export class PolygonChain implements Chain {
price,
};
}) as Promise<TokenBalance>[];
return safePromiseAllV1(promises);
return safePromiseAll(promises).then((items) => items.flat());
};
}

Expand Down Expand Up @@ -320,7 +320,7 @@ export class AvalancheChain implements Chain {
price,
};
}) as Promise<TokenBalance>[];
return safePromiseAllV1(promises);
return safePromiseAll(promises).then((items) => items.flat());
};
}

Expand Down Expand Up @@ -430,7 +430,7 @@ export class KlaytnChain implements Chain {
};
return balanceInfo;
}) as Promise<TokenBalance>[];
return safePromiseAllV1(promises);
return safePromiseAll(promises).then((items) => items.flat());
};
}

Expand Down Expand Up @@ -507,7 +507,7 @@ export class SolanaChain implements Chain {
price,
};
}) as Promise<TokenBalance>[];
return safePromiseAllV1(promises);
return safePromiseAll(promises).then((items) => items.flat());
};
}

Expand Down
2 changes: 1 addition & 1 deletion packages/bento-web/pages/_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import styled from 'styled-components';

import { LoadingProgress } from '@/components/LoadingProgress';
import { NavigationBar } from '@/components/NavigationBar';
import { PricingsProvider } from '@/hooks/pricings';
import { PricingsProvider } from '@/hooks/useCachedPricings';
import { GlobalStyle } from '@/styles/GlobalStyle';

Analytics.initialize();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ const getDeFiStakingsByWalletAddress = async (
const promisesForDelegations = KlayStation.getDelegations(walletAddress);

const stakings = (
await safePromiseAllV1([
await Promise.all([
promisesForStakings.catch(handleError),
promisesForDelegations.catch(handleError),
])
Expand Down
2 changes: 1 addition & 1 deletion packages/bento-web/src/dashboard/utils/useDeFis.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Wallet } from '@bento/common';
import { useEffect, useMemo, useState } from 'react';

import { useCachedPricings } from '@/hooks/pricings';
import { useCachedPricings } from '@/hooks/useCachedPricings';

import {
Valuation,
Expand Down
2 changes: 1 addition & 1 deletion packages/bento-web/src/dashboard/utils/useNFTBalances.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import chunk from 'lodash.chunk';
import groupBy from 'lodash.groupby';
import { useEffect, useState } from 'react';

import { useCachedPricings } from '@/hooks/pricings';
import { useCachedPricings } from '@/hooks/useCachedPricings';

import { NFTWalletBalance } from '@/dashboard/types/WalletBalance';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Wallet } from '@bento/common';
import produce from 'immer';
import { useEffect, useMemo, useState } from 'react';

import { useCachedPricings } from '@/hooks/pricings';
import { useCachedPricings } from '@/hooks/useCachedPricings';

import { KEYS_BY_NETWORK } from '@/constants/networks';
import {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { TokenInput } from '@bento/core';

import { GetCachedPrice } from '@/hooks/pricings';
import { GetCachedPrice } from '@/hooks/useCachedPricings';

import {
AmountWithOptionalValue,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { safePromiseAll } from '@bento/common';
import { pricesFromCoinGecko } from '@bento/core';
import { atom, useAtom, useAtomValue, useSetAtom } from 'jotai';
import React, { useCallback } from 'react';
import React, { useMemo } from 'react';

import { useInterval } from '@/hooks/useInterval';

import { Config } from '@/utils';

import { useClientCallback } from './useClientCallback';
import { useLazyEffect } from './useLazyEffect';

const SECONDS = 1_000;
Expand All @@ -27,70 +28,77 @@ const buildCacheStore = <T extends any>(prefix: string) => ({
localStorage.setItem(prefix, JSON.stringify({ ...prev, [key]: value }));
},
});
const CacheStore = buildCacheStore('@pricings');

type PricingMap = Record<string, number>;
export const pricingsAtom = atom<PricingMap>({});
export const coinGeckoIdsAtom = atom<string[]>([]);

const useCoinGeckoPrices = () => {
const CacheStore = useMemo(() => buildCacheStore('@pricings'), []);

const coinGeckoIds = useAtomValue(coinGeckoIdsAtom);
const [prices, setPrices] = useAtom(pricingsAtom);

const fetchPrices = useCallback(async () => {
if (!coinGeckoIds.length) {
return;
}

if (Config.ENVIRONMENT !== 'production') {
console.log('hit');
}

const cachedIds: string[] = [];
const cachedPrices = await safePromiseAll(
coinGeckoIds.map(async (coinGeckoId) => {
const cachedValue = await CacheStore.get(coinGeckoId).catch(() => null);
if (!cachedValue) {
return [coinGeckoId, 0];
}
const [value, cachedAt] = cachedValue as ValueVO;

if (cachedAt >= Date.now() - CACHE_TIME) {
cachedIds.push(coinGeckoId);
return [coinGeckoId, value];
}

return [coinGeckoId, 0];
}),
);
let cachedPricesObject: PricingMap | null = null;
if (cachedPrices.length > 0) {
cachedPricesObject = Object.fromEntries(cachedPrices);
setPrices(cachedPricesObject as PricingMap);
}

const cachedIdsSet = new Set(cachedIds);
const uncachedIds = coinGeckoIds.filter((id) => !cachedIdsSet.has(id));

const fetchedPrices =
uncachedIds.length === 0
? []
: await pricesFromCoinGecko(uncachedIds).then((prices) =>
Object.entries(prices),
const fetchPrices = useClientCallback(
async () => {
if (!coinGeckoIds.length) {
return;
}

if (Config.ENVIRONMENT !== 'production') {
console.log('hit');
}

const cachedIds: string[] = [];
const cachedPrices = await safePromiseAll(
coinGeckoIds.map(async (coinGeckoId) => {
const cachedValue = await CacheStore.get(coinGeckoId).catch(
() => null,
);
await safePromiseAll(
fetchedPrices.map(([key, price]) =>
CacheStore.set(key, [price, Date.now()]),
),
);
if (!cachedValue) {
return [coinGeckoId, 0];
}
const [value, cachedAt] = cachedValue as ValueVO;

const fetchedPricesObject = Object.fromEntries(fetchedPrices);
if (cachedAt >= Date.now() - CACHE_TIME) {
cachedIds.push(coinGeckoId);
return [coinGeckoId, value];
}

setPrices({
...cachedPricesObject,
...fetchedPricesObject,
});
}, [JSON.stringify(coinGeckoIds)]);
return [coinGeckoId, 0];
}),
);
let cachedPricesObject: PricingMap | null = null;
if (cachedPrices.length > 0) {
cachedPricesObject = Object.fromEntries(cachedPrices);
setPrices(cachedPricesObject as PricingMap);
}

const cachedIdsSet = new Set(cachedIds);
const uncachedIds = coinGeckoIds.filter((id) => !cachedIdsSet.has(id));

const fetchedPrices =
uncachedIds.length === 0
? []
: await pricesFromCoinGecko(uncachedIds).then((prices) =>
Object.entries(prices),
);
await safePromiseAll(
fetchedPrices.map(([key, price]) =>
CacheStore.set(key, [price, Date.now()]),
),
);

const fetchedPricesObject = Object.fromEntries(fetchedPrices);

setPrices({
...cachedPricesObject,
...fetchedPricesObject,
});
},
[JSON.stringify(coinGeckoIds)],
() => {},
);

useLazyEffect(
() => {
Expand Down Expand Up @@ -121,7 +129,7 @@ export const PricingsProvider: React.FC<React.PropsWithChildren> = ({
const [prices] = useAtom(pricingsAtom);
const setCoinGeckoIds = useSetAtom(coinGeckoIdsAtom);

const getCachedPrice = useCallback(
const getCachedPrice = useClientCallback(
(coinGeckoId: string | string[]) => {
const single = typeof coinGeckoId === 'string';
const ids = single ? [coinGeckoId] : coinGeckoId;
Expand All @@ -135,6 +143,7 @@ export const PricingsProvider: React.FC<React.PropsWithChildren> = ({
return single ? res[0] : res;
},
[prices],
() => 0,
) as GetCachedPrice;

return (
Expand Down
18 changes: 18 additions & 0 deletions packages/bento-web/src/hooks/useClientCallback.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { DependencyList, useCallback } from 'react';

import { isServer } from '@/utils';

export const useClientCallback = <T extends Function>(
callback: T,
deps: DependencyList,
fallback: T,
): T => {
const func = useCallback(() => {
if (isServer()) {
return fallback();
}
return callback();
}, deps);

return func as any as T;
};
7 changes: 5 additions & 2 deletions packages/bento-web/src/hooks/useLazyEffect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,20 @@ import {

import { debounce } from '@/utils/debounce';

import { useClientCallback } from './useClientCallback';

export function useLazyEffect(
effect: EffectCallback,
deps: DependencyList = [],
wait: number,
) {
const cleanUp = useRef<void | (() => void)>();
const effectRef = useRef<EffectCallback>();
effectRef.current = useCallback(effect, deps);
const lazyEffect = useCallback(
effectRef.current = useClientCallback(effect, deps, () => {});
const lazyEffect = useClientCallback(
debounce(() => (cleanUp.current = effectRef.current?.()), wait),
[],
() => {},
);
useEffect(lazyEffect, deps);
useEffect(() => {
Expand Down
2 changes: 2 additions & 0 deletions packages/bento-web/src/utils/devices.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export const isServer = (): boolean =>
typeof window === 'undefined' && typeof global !== 'undefined';
1 change: 1 addition & 0 deletions packages/bento-web/src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export { Analytics, type AnalyticsEvent } from './analytics';
export { axios } from './axios';
export { copyToClipboard } from './clipboard';
export { Config } from './Config';
export { isServer } from './devices';
export { FeatureFlags } from './FeatureFlag';
export { Supabase } from './Supabase';
export { throttle } from './throttle';
Expand Down