on master help sign in
txns: EIP1559 fee data

Also add a comment for future work on a race condition in Points.tsx

commit426669089f15916b5ac86095cee70ef52749f70b authortomholford <tomholford@users.noreply.github.com> dateFri 14 Oct 2022, 15:32 (4 years ago) parent505d3e2
4 files changed+79−41
src/components/L2/Dropdowns/FeeDropdown.tsx+20−7 src/lib/getSuggestedGasPrice.js+36−20 src/lib/useGasPrice.js+16−14 src/views/Points.tsx+7
src/components/L2/Dropdowns/FeeDropdown.tsx+20−7
@@ -8,13 +8,16 @@ import './FeeDropdown.scss';
88
99const PRICE_LABELS = ['Fast', 'Normal', 'Slow'];
1010
11−export interface GasPrice {
11+export interface GasPriceData {
1212 price: number;
1313 wait: string;
14+ maxFeePerGas: number;
15+ maxPriorityFeePerGas: number;
16+ suggestedBaseFeePerGas: number;
1417}
1518
1619export const formatWait = (wait: number) => Math.round(wait * 100) / 100;
17−export const formatDisplay = ({ price, wait }: GasPrice) =>
20+export const formatDisplay = ({ price, wait }: GasPriceData) =>
1821 `${price} gwei (${wait} min)`;
1922
2023export default function FeeDropdown({
@@ -22,12 +25,16 @@ export default function FeeDropdown({
2225}: {
2326 setGasPrice: (g: number) => void;
2427}) {
25− const { suggestedGasPrices } = useGasPrice(DEFAULT_GAS_PRICE_GWEI);
28+ const { suggestedGasPrices }: { suggestedGasPrices: {
29+ fast: GasPriceData,
30+ average: GasPriceData,
31+ low: GasPriceData,
32+ }} = useGasPrice(DEFAULT_GAS_PRICE_GWEI);
2633
2734 const [open, setOpen] = useState(false);
2835 const [useCustom, setUseCustom] = useState(false);
2936 const [custom, setCustom] = useState<string | undefined>();
30− const [selected, setSelected] = useState<GasPrice>(
37+ const [selected, setSelected] = useState<GasPriceData>(
3138 suggestedGasPrices.average
3239 );
3340
@@ -51,7 +58,13 @@ export default function FeeDropdown({
5158 customWait = `< ${fast.wait}`;
5259 }
5360
54− setSelected({ price: cleanedNum, wait: customWait });
61+ setSelected({
62+ price: cleanedNum,
63+ wait: customWait,
64+ maxFeePerGas: cleanedNum,
65+ maxPriorityFeePerGas: cleanedNum,
66+ suggestedBaseFeePerGas: cleanedNum
67+ });
5568 };
5669
5770 useEffect(() => {
@@ -59,7 +72,7 @@ export default function FeeDropdown({
5972 }, [suggestedGasPrices]);
6073
6174 const selectPrice = useCallback(
62− (value: GasPrice) => () => {
75+ (value: GasPriceData) => () => {
6376 setSelected(value);
6477 setGasPrice(value.price);
6578 setOpen(false);
@@ -97,7 +110,7 @@ export default function FeeDropdown({
97110 toggleOpen={() => setOpen(!open)}>
98111 <Box className="prices">
99112 {Object.values(suggestedGasPrices).map(
100− (value: GasPrice, ind: number) => (
113+ (value: GasPriceData, ind: number) => (
101114 <Row
102115 className="price"
103116 onClick={selectPrice(value)}
src/lib/getSuggestedGasPrice.js+36−20
@@ -31,44 +31,60 @@ export default async function getSuggestedGasPrice(networkType) {
3131 case NETWORK_TYPES.LOCAL:
3232 default:
3333 try {
34− const etherscanGas = await fetch(
35− 'https://api.etherscan.io/api' +
36− '?module=gastracker' +
37− '&action=gasoracle' +
38− '&apikey=CG52E4R96W56GIKUI4IJ8CH9EZIXPUW1W8',
39− {
40− method: 'GET',
41− cache: 'no-cache',
42− }
43− );
34+ const [etherscanGas, ethgasstationGas] = await Promise.all([
35+ fetch(
36+ 'https://api.etherscan.io/api' +
37+ '?module=gastracker' +
38+ '&action=gasoracle' +
39+ '&apikey=CG52E4R96W56GIKUI4IJ8CH9EZIXPUW1W8',
40+ {
41+ method: 'GET',
42+ cache: 'no-cache',
43+ }
44+ ),
45+ fetch(
46+ 'https://ethgasstation.info/json/ethgasAPI.json',
47+ {
48+ method: 'GET',
49+ cache: 'no-cache',
50+ }
51+ )
52+ ]);
4453
45− const ethgasstationGas = await fetch(
46− 'https://ethgasstation.info/json/ethgasAPI.json',
47− {
48− method: 'GET',
49− cache: 'no-cache',
50− }
51− );
54+ const [etherscanGasJson, ethgasstationGasJson] = await Promise.all([
55+ etherscanGas.json(),
56+ ethgasstationGas.json()
57+ ])
5258
53− const etherscanGasJson = await etherscanGas.json();
54−
55− const ethgasstationGasJson = await ethgasstationGas.json();
59+ const suggestedBaseFeePerGas = Number(etherscanGasJson.result.suggestBaseFee);
5660
61+ // Calculations inspired by:
62+ // https://github.com/liquality/chainify/blob/6e8243e8daf4dc219dcfd7df144ead3ff6183b26/packages/evm/lib/fee/EIP1559FeeApiProvider/ethereum.ts#L5
5763 return {
5864 fast: {
5965 price: minGas(etherscanGasJson.result.FastGasPrice),
6066 wait: formatWait(ethgasstationGasJson.fastWait),
67+ maxFeePerGas: minGas(etherscanGasJson.result.FastGasPrice),
68+ maxPriorityFeePerGas: (etherscanGasJson.result.FastGasPrice - suggestedBaseFeePerGas),
69+ suggestedBaseFeePerGas
6170 },
6271 average: {
6372 price: minGas(etherscanGasJson.result.ProposeGasPrice),
6473 wait: formatWait(ethgasstationGasJson.avgWait),
74+ maxFeePerGas: minGas(etherscanGasJson.result.ProposeGasPrice),
75+ maxPriorityFeePerGas: (etherscanGasJson.result.ProposeGasPrice - suggestedBaseFeePerGas),
76+ suggestedBaseFeePerGas
6577 },
6678 low: {
6779 price: minGas(etherscanGasJson.result.SafeGasPrice),
6880 wait: formatWait(ethgasstationGasJson.safeLowWait),
81+ maxFeePerGas: minGas(etherscanGasJson.result.SafeGasPrice),
82+ maxPriorityFeePerGas: (etherscanGasJson.result.SafeGasPrice - suggestedBaseFeePerGas),
83+ suggestedBaseFeePerGas
6984 },
7085 };
7186 } catch (e) {
87+ console.warn(e);
7288 return defaultGasValues(DEFAULT_GAS_PRICE_GWEI);
7389 }
7490 }
src/lib/useGasPrice.js+16−14
@@ -15,29 +15,31 @@ import { DEFAULT_GAS_PRICE_GWEI } from './constants';
1515 * @param {Number} initialGasPrice the initial gas price available instantly
1616 */
1717export default function useGasPrice(initialGasPrice = DEFAULT_GAS_PRICE_GWEI) {
18+ const [mounted, setMounted] = useState(false);
1819 const { networkType } = useNetwork();
1920 const [suggestedGasPrices, setSuggestedGasPrices] = useState(
2021 defaultGasValues(initialGasPrice)
2122 ); // fast, average, low. In gwei
2223 const [gasPrice, setGasPrice] = useState(initialGasPrice); // gwei
2324
24− useEffect(() => {
25− let mounted = true;
26−
27− (async () => {
28− const suggestedGasPrices = await getSuggestedGasPrices(networkType);
25+ const fetchPrices = useCallback(async () => {
26+ if (!mounted) {
27+ return;
28+ }
2929
30− if (!mounted) {
31− return;
32− }
30+ const suggestedGasPrices = await getSuggestedGasPrices(networkType);
31+ console.log(suggestedGasPrices);
3332
34− // TODO: BN
35− setSuggestedGasPrices(suggestedGasPrices);
36− setGasPrice(suggestedGasPrices.average.price);
37− })();
33+ // TODO: BN
34+ setSuggestedGasPrices(suggestedGasPrices);
35+ setGasPrice(suggestedGasPrices.average.price);
36+ }, [mounted]);
3837
39− return () => (mounted = true);
40− }, [networkType]);
38+ useEffect(() => {
39+ setMounted(true);
40+ fetchPrices()
41+ return () => (setMounted(false));
42+ }, [mounted, networkType]);
4143
4244 const resetGasPrice = useCallback(
4345 () => setGasPrice(suggestedGasPrices.average.price),
src/views/Points.tsx+7
@@ -67,6 +67,13 @@ export default function Points() {
6767 const { wallet }: any = useWallet();
6868 const { pop, push, names }: any = useHistory();
6969 const { setPointCursor }: any = usePointCursor();
70+ /**
71+ * TODO: there is a race condition here; sometimes the pointCache is not
72+ * loaded by the time this view renders, which then causes a crash when
73+ * attempting to destructure.
74+ *
75+ * Same is also true for isEclipticOwner.
76+ */
7077 const { controlledPoints, getDetails }: any = usePointCache();
7178 const { contracts }: any = useNetwork();
7279 const isEclipticOwner = useIsEclipticOwner();