From f5e3a80fbbba11464b09e98a61942cf3fe67b196 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Tue, 20 Feb 2024 15:40:35 +0000 Subject: [PATCH 1/2] feat: sub 1s load time --- .../render-transaction/insert-table-data.ts | 47 +++++++++++++--- .../render-transaction/render-token-symbol.ts | 29 +++------- .../render-transaction/render-transaction.ts | 28 ++-------- static/scripts/rewards/web3/erc20-permit.ts | 56 +++++++++---------- static/scripts/rewards/web3/wallet.ts | 3 +- 5 files changed, 83 insertions(+), 80 deletions(-) diff --git a/static/scripts/rewards/render-transaction/insert-table-data.ts b/static/scripts/rewards/render-transaction/insert-table-data.ts index 565bc1ce..0da37199 100644 --- a/static/scripts/rewards/render-transaction/insert-table-data.ts +++ b/static/scripts/rewards/render-transaction/insert-table-data.ts @@ -1,30 +1,61 @@ -import { BigNumber, ethers } from "ethers"; +import { ethers } from "ethers"; import { app } from "."; import { Erc20Permit, Erc721Permit } from "./tx-type"; +import { fetchTreasury } from "../web3/erc20-permit"; +import { renderTokenSymbol } from "./render-token-symbol"; +import { networkExplorers } from "../constants"; export function shortenAddress(address: string): string { return `${address.slice(0, 10)}...${address.slice(-8)}`; } -export function insertErc20PermitTableData( +export async function insertErc20PermitTableData( permit: Erc20Permit, - table: Element, - treasury: { balance: BigNumber; allowance: BigNumber; decimals: number; symbol: string } -): Element { + provider: ethers.providers.JsonRpcProvider, + symbol: string, + decimals: number, + table: Element +) { const requestedAmountElement = document.getElementById("rewardAmount") as Element; renderToFields(permit.transferDetails.to, app.currentExplorerUrl); renderTokenFields(permit.permit.permitted.token, app.currentExplorerUrl); + renderDetailsFields([ { name: "From", value: `${permit.owner}` }, { name: "Expiry", value: permit.permit.deadline.lte(Number.MAX_SAFE_INTEGER.toString()) ? new Date(permit.permit.deadline.toNumber()).toLocaleString() : undefined, }, - { name: "Balance", value: treasury.balance.gte(0) ? `${ethers.utils.formatUnits(treasury.balance, treasury.decimals)} ${treasury.symbol}` : "N/A" }, - { name: "Allowance", value: treasury.allowance.gte(0) ? `${ethers.utils.formatUnits(treasury.allowance, treasury.decimals)} ${treasury.symbol}` : "N/A" }, + { name: "Balance", value: "Loading..." }, + { name: "Allowance", value: "Loading..." }, ]); + + renderTokenSymbol({ + requestedAmountElement, + tokenAddress: permit.permit.permitted.token, + ownerAddress: permit.owner, + amount: permit.transferDetails.requestedAmount, + explorerUrl: networkExplorers[permit.networkId], + symbol, + decimals, + }); + + // Optimistically rendered what we can so consider it loaded + table.setAttribute(`data-claim`, "ok"); + table.setAttribute(`data-contract-loaded`, "true"); table.setAttribute(`data-claim-rendered`, "true"); - return requestedAmountElement; + + const { balance, allowance } = await fetchTreasury(permit.permit.permitted.token, permit.owner, provider); + + renderDetailsFields([ + { name: "From", value: `${permit.owner}` }, + { + name: "Expiry", + value: permit.permit.deadline.lte(Number.MAX_SAFE_INTEGER.toString()) ? new Date(permit.permit.deadline.toNumber()).toLocaleString() : undefined, + }, + { name: "Balance", value: balance.gte(0) ? `${ethers.utils.formatUnits(balance, decimals)} ${symbol}` : "N/A" }, + { name: "Allowance", value: allowance.gte(0) ? `${ethers.utils.formatUnits(allowance, decimals)} ${symbol}` : "N/A" }, + ]); } export function insertErc721PermitTableData(permit: Erc721Permit, table: Element): Element { diff --git a/static/scripts/rewards/render-transaction/render-token-symbol.ts b/static/scripts/rewards/render-transaction/render-token-symbol.ts index d7af472a..429bda7a 100644 --- a/static/scripts/rewards/render-transaction/render-token-symbol.ts +++ b/static/scripts/rewards/render-transaction/render-token-symbol.ts @@ -1,6 +1,5 @@ -import { BigNumberish, Contract, utils } from "ethers"; +import { BigNumberish, utils } from "ethers"; import { getErc20Contract } from "../helpers"; -import { MaxUint256 } from "@uniswap/permit2-sdk"; import { JsonRpcProvider } from "@ethersproject/providers"; export const tokens = [ @@ -14,37 +13,27 @@ export const tokens = [ }, ]; -export async function renderTokenSymbol({ - table, +export function renderTokenSymbol({ requestedAmountElement, tokenAddress, ownerAddress, amount, explorerUrl, - provider, + symbol, + decimals, }: { - table: Element; requestedAmountElement: Element; tokenAddress: string; ownerAddress: string; amount: BigNumberish; explorerUrl: string; - provider: JsonRpcProvider; -}): Promise { - let symbol = tokenAddress === tokens[0].address ? tokens[0].name : tokenAddress === tokens[1].address ? tokens[1].name : false; - let decimals = tokenAddress === tokens[0].address ? 18 : tokenAddress === tokens[1].address ? 18 : MaxUint256; - - if (!symbol || decimals === MaxUint256) { - const contract: Contract = await getErc20Contract(tokenAddress, provider); - symbol = await contract.symbol(); - decimals = await contract.decimals(); - } - - table.setAttribute(`data-contract-loaded`, "true"); - requestedAmountElement.innerHTML = `${utils.formatUnits( + symbol: string; + decimals: number; +}) { + return (requestedAmountElement.innerHTML = `${utils.formatUnits( amount, decimals - )} ${symbol}`; + )} ${symbol}`); } export async function renderNftSymbol({ diff --git a/static/scripts/rewards/render-transaction/render-transaction.ts b/static/scripts/rewards/render-transaction/render-transaction.ts index 7d416e6f..256af563 100644 --- a/static/scripts/rewards/render-transaction/render-transaction.ts +++ b/static/scripts/rewards/render-transaction/render-transaction.ts @@ -4,13 +4,12 @@ import { Value } from "@sinclair/typebox/value"; import { networkExplorers } from "../constants"; import { getOptimalProvider } from "../helpers"; import { claimButton, hideClaimButton, resetClaimButton } from "../toaster"; -import { claimErc20PermitHandler, fetchTreasury, generateInvalidatePermitAdminControl } from "../web3/erc20-permit"; +import { claimErc20PermitHandler, generateInvalidatePermitAdminControl, processERC20 } from "../web3/erc20-permit"; import { claimErc721PermitHandler } from "../web3/erc721-permit"; -import { handleNetwork } from "../web3/wallet"; import { app } from "./index"; -import { insertErc20PermitTableData, insertErc721PermitTableData } from "./insert-table-data"; +import { insertErc721PermitTableData } from "./insert-table-data"; import { renderEnsName } from "./render-ens-name"; -import { renderNftSymbol, renderTokenSymbol } from "./render-token-symbol"; +import { renderNftSymbol } from "./render-token-symbol"; import { setClaimMessage } from "./set-claim-message"; import { claimTxT } from "./tx-type"; import { removeAllEventListeners } from "./utils"; @@ -35,7 +34,7 @@ export async function init() { app.claimTxs = claimTxs; optimalRPC = await getOptimalProvider(app.currentTx?.networkId ?? app.claimTxs[0].networkId); - handleNetwork(app.currentTx?.networkId ?? app.claimTxs[0].networkId).catch(console.error); + // handleNetwork(app.currentTx?.networkId ?? app.claimTxs[0].networkId).catch(console.error); } catch (error) { console.error(error); setClaimMessage({ type: "Error", message: `Invalid claim data passed in URL` }); @@ -86,7 +85,7 @@ export async function init() { } } - renderTransaction(optimalRPC, true).catch(console.error); + renderTransaction(optimalRPC).catch(console.error); } function setPagination(nextTxButton: Element | null, prevTxButton: Element | null) { @@ -123,25 +122,10 @@ export async function renderTransaction(provider: JsonRpcProvider, nextTx?: bool return false; } - handleNetwork(app.currentTx.networkId).catch(console.error); - if (app.currentTx.type === "erc20-permit") { - const treasury = await fetchTreasury(app.currentTx, provider); + await processERC20(app.currentTx.permit.permitted.token, provider, app.currentTx, table); // insert tx data into table - const requestedAmountElement = insertErc20PermitTableData(app.currentTx, table, treasury); - table.setAttribute(`data-claim`, "ok"); - - renderTokenSymbol({ - tokenAddress: app.currentTx.permit.permitted.token, - ownerAddress: app.currentTx.owner, - amount: app.currentTx.transferDetails.requestedAmount, - explorerUrl: networkExplorers[app.currentTx.networkId], - table, - requestedAmountElement, - provider, - }).catch(console.error); - const toElement = document.getElementById(`rewardRecipient`) as Element; renderEnsName({ element: toElement, address: app.currentTx.transferDetails.to }).catch(console.error); diff --git a/static/scripts/rewards/web3/erc20-permit.ts b/static/scripts/rewards/web3/erc20-permit.ts index 014f68fb..5417b7ac 100644 --- a/static/scripts/rewards/web3/erc20-permit.ts +++ b/static/scripts/rewards/web3/erc20-permit.ts @@ -9,35 +9,35 @@ import { connectWallet } from "./wallet"; import invalidateButton from "../invalidate-component"; import { JsonRpcProvider } from "@ethersproject/providers"; import { tokens } from "../render-transaction/render-token-symbol"; +import { insertErc20PermitTableData } from "../render-transaction/insert-table-data"; -export async function fetchTreasury( - permit: Erc20Permit, - provider: JsonRpcProvider -): Promise<{ balance: BigNumber; allowance: BigNumber; decimals: number; symbol: string }> { - try { - const tokenAddress = permit.permit.permitted.token.toLowerCase(); - const tokenContract = await getErc20Contract(tokenAddress, provider); - - if (tokenAddress === tokens[0].address || tokenAddress === tokens[1].address) { - const decimals = tokenAddress === tokens[0].address ? 18 : tokenAddress === tokens[1].address ? 18 : -1; - const symbol = tokenAddress === tokens[0].address ? tokens[0].name : tokenAddress === tokens[1].address ? tokens[1].name : ""; - - const [balance, allowance] = await Promise.all([tokenContract.balanceOf(permit.owner), tokenContract.allowance(permit.owner, permit2Address)]); - - return { balance, allowance, decimals, symbol }; - } else { - console.log(`Hardcode this token in render-token-symbol.ts and save two calls: ${tokenAddress}`); - const [balance, allowance, decimals, symbol] = await Promise.all([ - tokenContract.balanceOf(permit.owner), - tokenContract.allowance(permit.owner, permit2Address), - tokenContract.decimals(), - tokenContract.symbol(), - ]); - - return { balance, allowance, decimals, symbol }; +export async function processERC20(tokenAddress: string, provider: JsonRpcProvider, permit: Erc20Permit, table: Element) { + let symbol = tokenAddress === tokens[0].address ? tokens[0].name : tokenAddress === tokens[1].address ? tokens[1].name : ""; + let decimals = tokenAddress === tokens[0].address ? 18 : tokenAddress === tokens[1].address ? 18 : -1; + const contract = await getErc20Contract(tokenAddress, provider); + + if (!symbol || decimals === -1) { + try { + symbol = contract.symbol(); + decimals = contract.decimals(); + } catch (err) { + throw new Error(`Error fetching symbol and decimals for token address: ${tokenAddress}`); } - } catch (error: unknown) { - return { balance: BigNumber.from(-1), allowance: BigNumber.from(-1), decimals: -1, symbol: "" }; + } + + await insertErc20PermitTableData(permit, provider, symbol, decimals, table); +} + +export async function fetchTreasury(contractAddr: string, owner: string, provider: JsonRpcProvider) { + const contract = await getErc20Contract(contractAddr, provider); + + try { + const [balance, allowance] = await Promise.all([contract.balanceOf(owner), contract.allowance(owner, permit2Address)]); + return { balance, allowance } as { balance: BigNumber; allowance: BigNumber }; + } catch (err) { + console.log(err); + console.log(contractAddr); + throw new Error(`Error fetching treasury data for token address: ${contractAddr}`); } } @@ -85,7 +85,7 @@ export async function checkPermitClaimable(permit: Erc20Permit, signer: ethers.p return false; } - const { balance, allowance } = await fetchTreasury(permit, provider); + const { balance, allowance } = await fetchTreasury(permit.permit.permitted.token, permit.owner, provider); const permitted = BigNumber.from(permit.permit.permitted.amount); const isSolvent = balance.gte(permitted); const isAllowed = allowance.gte(permitted); diff --git a/static/scripts/rewards/web3/wallet.ts b/static/scripts/rewards/web3/wallet.ts index 56ce5e73..34766b85 100644 --- a/static/scripts/rewards/web3/wallet.ts +++ b/static/scripts/rewards/web3/wallet.ts @@ -33,8 +33,7 @@ export async function handleNetwork(desiredNetworkId: number) { invalidateButton.disabled = true; } - const chainIdHex = String(web3provider.network.chainId); - const currentNetworkId = parseInt(chainIdHex, 16); + const currentNetworkId = (await web3provider.getNetwork()).chainId; // watch for network changes window.ethereum.on("chainChanged", (newNetworkId: T | string) => handleIfOnCorrectNetwork(parseInt(newNetworkId as string, 16), desiredNetworkId)); From 7fab1b4dcf224ebca7ed50e97d7c4ef713403838 Mon Sep 17 00:00:00 2001 From: Keyrxng <106303466+Keyrxng@users.noreply.github.com> Date: Tue, 20 Feb 2024 16:10:54 +0000 Subject: [PATCH 2/2] chore: fetch inside try --- static/scripts/rewards/web3/erc20-permit.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/static/scripts/rewards/web3/erc20-permit.ts b/static/scripts/rewards/web3/erc20-permit.ts index 5417b7ac..fd26d9f5 100644 --- a/static/scripts/rewards/web3/erc20-permit.ts +++ b/static/scripts/rewards/web3/erc20-permit.ts @@ -14,10 +14,10 @@ import { insertErc20PermitTableData } from "../render-transaction/insert-table-d export async function processERC20(tokenAddress: string, provider: JsonRpcProvider, permit: Erc20Permit, table: Element) { let symbol = tokenAddress === tokens[0].address ? tokens[0].name : tokenAddress === tokens[1].address ? tokens[1].name : ""; let decimals = tokenAddress === tokens[0].address ? 18 : tokenAddress === tokens[1].address ? 18 : -1; - const contract = await getErc20Contract(tokenAddress, provider); if (!symbol || decimals === -1) { try { + const contract = await getErc20Contract(tokenAddress, provider); symbol = contract.symbol(); decimals = contract.decimals(); } catch (err) { @@ -29,16 +29,15 @@ export async function processERC20(tokenAddress: string, provider: JsonRpcProvid } export async function fetchTreasury(contractAddr: string, owner: string, provider: JsonRpcProvider) { - const contract = await getErc20Contract(contractAddr, provider); - try { + const contract = await getErc20Contract(contractAddr, provider); const [balance, allowance] = await Promise.all([contract.balanceOf(owner), contract.allowance(owner, permit2Address)]); return { balance, allowance } as { balance: BigNumber; allowance: BigNumber }; } catch (err) { console.log(err); - console.log(contractAddr); - throw new Error(`Error fetching treasury data for token address: ${contractAddr}`); } + + return { balance: BigNumber.from(0), allowance: BigNumber.from(0) }; } export function claimErc20PermitHandler(permit: Erc20Permit, provider: JsonRpcProvider) {