From 7d49221d8ddebf32e71c325081b06de469d58646 Mon Sep 17 00:00:00 2001 From: james-a-morris Date: Wed, 25 Oct 2023 17:26:21 -0400 Subject: [PATCH 01/10] feat: add redis caching support for getBalance --- api/_imports.ts | 5 ++++ api/_utils.ts | 59 ++++++++++++++++------------------------- api/account-balance.ts | 60 ------------------------------------------ api/limits.ts | 17 +++++++++++- api/suggested-fees.ts | 18 ++++++++++++- package.json | 1 + yarn.lock | 5 ++++ 7 files changed, 67 insertions(+), 98 deletions(-) create mode 100644 api/_imports.ts delete mode 100644 api/account-balance.ts diff --git a/api/_imports.ts b/api/_imports.ts new file mode 100644 index 000000000..a1b1bcd66 --- /dev/null +++ b/api/_imports.ts @@ -0,0 +1,5 @@ +import * as fetch from "node-fetch"; + +if (!globalThis.fetch) { + (globalThis as any).fetch = fetch; +} diff --git a/api/_utils.ts b/api/_utils.ts index 586076971..f18284dc6 100644 --- a/api/_utils.ts +++ b/api/_utils.ts @@ -1,3 +1,4 @@ +import "./_imports"; import { AcceleratingDistributor__factory } from "@across-protocol/across-token/dist/typechain"; import { ERC20__factory, @@ -11,7 +12,6 @@ import { Log, Logging } from "@google-cloud/logging"; import axios from "axios"; import { BigNumber, ethers, providers, utils } from "ethers"; import { StructError, define } from "superstruct"; - import enabledMainnetRoutesAsJson from "../src/data/routes_1_0xc186fA914353c44b2E33eBE05f21846F1048bEda.json"; import enabledGoerliRoutesAsJson from "../src/data/routes_5_0x0e2817C49698cc0874204AeDf7c72Be2Bb7fCD5d.json"; @@ -36,6 +36,7 @@ import { defaultRelayerAddressOverride, } from "./_constants"; import { PoolStateResult } from "./_types"; +import { kv } from "@vercel/kv"; type LoggingUtility = sdk.relayFeeCalculator.Logger; @@ -620,45 +621,31 @@ export const isRouteEnabled = ( * @param token The valid ERC20 token address on the given `chainId`. * @returns A promise that resolves to the BigNumber of the balance */ -export const getBalance = ( - chainId: string | number, - account: string, - token: string -): Promise => { - return sdk.utils.getTokenBalance( - account, - token, - getProvider(Number(chainId)), - BLOCK_TAG_LAG - ); -}; - -/** - * Resolves the cached balance of a given ERC20 token at a provided address. If no token is provided, the balance of the - * native currency will be returned. - * @param chainId The blockchain Id to query against - * @param account A valid Web3 wallet address - * @param token The valid ERC20 token address on the given `chainId`. - * @returns A promise that resolves to the BigNumber of the balance - */ -export const getCachedTokenBalance = async ( +export const getBalance = async ( chainId: string | number, account: string, token: string ): Promise => { - // Make the request to the vercel API. - const response = await axios.get<{ balance: string }>( - `${resolveVercelEndpoint()}/api/account-balance`, - { - params: { - chainId, - account, - token, - }, - } - ); - // Return the balance - return BigNumber.from(response.data.balance); + const key = `balance_${chainId}-${account}-${token}`.toLowerCase(); + const data = await kv.get(key); + if (sdk.utils.isDefined(data)) { + return BigNumber.from(data); + } else { + const balance = await sdk.utils.getTokenBalance( + account, + token, + getProvider(Number(chainId)), + BLOCK_TAG_LAG // We should do this for consistency + ); + await kv.set(key, balance.toString(), { + ex: 60 * 5, // 5 minutes + }); + getLogger().debug({ + at: "_utils#getBalance", + message: `Cached balance for ${key}: ${balance}`, + }); + return balance; + } }; /** diff --git a/api/account-balance.ts b/api/account-balance.ts deleted file mode 100644 index 56be95685..000000000 --- a/api/account-balance.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { VercelResponse } from "@vercel/node"; -import { assert, Infer, type, string } from "superstruct"; -import { TypedVercelRequest } from "./_types"; -import { - getBalance, - getLogger, - handleErrorCondition, - validAddress, -} from "./_utils"; - -const AccountBalanceQueryParamsSchema = type({ - token: validAddress(), - account: validAddress(), - chainId: string(), -}); - -type AccountBalanceQueryParams = Infer; - -const handler = async ( - { query }: TypedVercelRequest, - response: VercelResponse -) => { - const logger = getLogger(); - logger.debug({ - at: "AccountBalance", - message: "Query data", - query, - }); - try { - // Validate the query parameters - assert(query, AccountBalanceQueryParamsSchema); - // Deconstruct the query parameters - let { token, account, chainId } = query; - // Rely on the utils to query the balance of the account for the token - const balance = await getBalance(chainId, account, token); - // Package the response - const result = { - balance: balance.toString(), - account: account, - token: token, - }; - // Log the response - logger.debug({ - at: "AccountBalance", - message: "Response data", - responseJson: result, - }); - // Set the caching headers that will be used by the CDN. - response.setHeader( - "Cache-Control", - "s-maxage=150, stale-while-revalidate=150" - ); - // Return the response - response.status(200).json(result); - } catch (error: unknown) { - return handleErrorCondition("account-balance", response, logger, error); - } -}; - -export default handler; diff --git a/api/limits.ts b/api/limits.ts index c1e6a2152..1a8ce98ba 100644 --- a/api/limits.ts +++ b/api/limits.ts @@ -19,7 +19,6 @@ import { getRelayerFeeDetails, getCachedTokenPrice, getTokenDetails, - getCachedTokenBalance, maxBN, minBN, isRouteEnabled, @@ -30,8 +29,12 @@ import { getProvider, HUB_POOL_CHAIN_ID, ENABLED_ROUTES, +<<<<<<< HEAD getDefaultRelayerAddress, sendResponse, +======= + getBalance, +>>>>>>> 5797e0a6 (feat: add redis caching support for getBalance) } from "./_utils"; const LimitsQueryParamsSchema = object({ @@ -165,19 +168,31 @@ const handler = async ( hubPool.callStatic.multicall(multicallInput, { blockTag: BLOCK_TAG_LAG }), Promise.all( fullRelayers.map((relayer) => +<<<<<<< HEAD getCachedTokenBalance(destinationChainId!, relayer, destinationToken) +======= + getBalance(destinationChainId!, destinationToken, relayer) +>>>>>>> 5797e0a6 (feat: add redis caching support for getBalance) ) ), Promise.all( transferRestrictedRelayers.map((relayer) => +<<<<<<< HEAD getCachedTokenBalance(destinationChainId!, relayer, destinationToken) +======= + getBalance(destinationChainId!, destinationToken, relayer) +>>>>>>> 5797e0a6 (feat: add redis caching support for getBalance) ) ), Promise.all( fullRelayers.map((relayer) => destinationChainId === "1" ? ethers.BigNumber.from("0") +<<<<<<< HEAD : getCachedTokenBalance("1", relayer, l1Token) +======= + : getBalance("1", l1Token, relayer) +>>>>>>> 5797e0a6 (feat: add redis caching support for getBalance) ) ), ]); diff --git a/api/suggested-fees.ts b/api/suggested-fees.ts index 622fa00ef..0d8cbbf98 100644 --- a/api/suggested-fees.ts +++ b/api/suggested-fees.ts @@ -29,8 +29,12 @@ import { HUB_POOL_CHAIN_ID, ENABLED_ROUTES, getSpokePoolAddress, +<<<<<<< HEAD getCachedTokenBalance, getDefaultRelayerAddress, +======= + getBalance, +>>>>>>> 5797e0a6 (feat: add redis caching support for getBalance) } from "./_utils"; const SuggestedFeesQueryParamsSchema = type({ @@ -113,10 +117,18 @@ const handler = async ( // Our message encoding is a hex string, so we need to check that the length is even. throw new InputError("Message must be an even hex string"); } +<<<<<<< HEAD const isRecipientAContract = await sdk.utils.isContractDeployedToAddress( recipient, getProvider(destinationChainId) ); +======= + const isRecipientAContract = + (await sdk.utils.isContractDeployedToAddress( + recipientAddress, + provider + )) || true; +>>>>>>> 5797e0a6 (feat: add redis caching support for getBalance) if (!isRecipientAContract) { throw new InputError( "Recipient must be a contract when a message is provided" @@ -135,9 +147,13 @@ const handler = async ( `Could not resolve token address on ${destinationChainId} for ${l1Token}` ); } - const balanceOfToken = await getCachedTokenBalance( + const balanceOfToken = await getBalance( destinationChainId, +<<<<<<< HEAD relayer, +======= + relayerAddress, +>>>>>>> 5797e0a6 (feat: add redis caching support for getBalance) destinationToken ); if (balanceOfToken.lt(amountInput)) { diff --git a/package.json b/package.json index dd58b1a38..27dae781d 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "jose": "^4.9.3", "lodash-es": "^4.17.21", "luxon": "^3.3.0", + "node-fetch": "2", "numeral": "^2.0.6", "react": "^17.0.2", "react-device-detect": "^2.2.2", diff --git a/yarn.lock b/yarn.lock index 4694b56ea..09c37b3dd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -27953,6 +27953,11 @@ whatwg-fetch@^2.0.4: resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz#dde6a5df315f9d39991aa17621853d720b85566f" integrity sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng== +whatwg-fetch@^3.4.1: + version "3.6.19" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.19.tgz#caefd92ae630b91c07345537e67f8354db470973" + integrity sha512-d67JP4dHSbm2TrpFj8AbO8DnL1JXL5J9u0Kq2xW6d0TFDbCA3Muhdt8orXC22utleTVj7Prqt82baN6RBvnEgw== + whatwg-mimetype@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz#5fa1a7623867ff1af6ca3dc72ad6b8a4208beba7" From 407b7701413f729bb24797719402a606d0abd18c Mon Sep 17 00:00:00 2001 From: james-a-morris Date: Thu, 14 Dec 2023 15:34:02 -0500 Subject: [PATCH 02/10] fix: merge issues --- api/limits.ts | 17 +---------------- api/suggested-fees.ts | 16 ---------------- 2 files changed, 1 insertion(+), 32 deletions(-) diff --git a/api/limits.ts b/api/limits.ts index 1a8ce98ba..5211d114f 100644 --- a/api/limits.ts +++ b/api/limits.ts @@ -29,12 +29,9 @@ import { getProvider, HUB_POOL_CHAIN_ID, ENABLED_ROUTES, -<<<<<<< HEAD + getBalance, getDefaultRelayerAddress, sendResponse, -======= - getBalance, ->>>>>>> 5797e0a6 (feat: add redis caching support for getBalance) } from "./_utils"; const LimitsQueryParamsSchema = object({ @@ -168,31 +165,19 @@ const handler = async ( hubPool.callStatic.multicall(multicallInput, { blockTag: BLOCK_TAG_LAG }), Promise.all( fullRelayers.map((relayer) => -<<<<<<< HEAD - getCachedTokenBalance(destinationChainId!, relayer, destinationToken) -======= getBalance(destinationChainId!, destinationToken, relayer) ->>>>>>> 5797e0a6 (feat: add redis caching support for getBalance) ) ), Promise.all( transferRestrictedRelayers.map((relayer) => -<<<<<<< HEAD - getCachedTokenBalance(destinationChainId!, relayer, destinationToken) -======= getBalance(destinationChainId!, destinationToken, relayer) ->>>>>>> 5797e0a6 (feat: add redis caching support for getBalance) ) ), Promise.all( fullRelayers.map((relayer) => destinationChainId === "1" ? ethers.BigNumber.from("0") -<<<<<<< HEAD - : getCachedTokenBalance("1", relayer, l1Token) -======= : getBalance("1", l1Token, relayer) ->>>>>>> 5797e0a6 (feat: add redis caching support for getBalance) ) ), ]); diff --git a/api/suggested-fees.ts b/api/suggested-fees.ts index 0d8cbbf98..f276de7b9 100644 --- a/api/suggested-fees.ts +++ b/api/suggested-fees.ts @@ -29,12 +29,8 @@ import { HUB_POOL_CHAIN_ID, ENABLED_ROUTES, getSpokePoolAddress, -<<<<<<< HEAD - getCachedTokenBalance, getDefaultRelayerAddress, -======= getBalance, ->>>>>>> 5797e0a6 (feat: add redis caching support for getBalance) } from "./_utils"; const SuggestedFeesQueryParamsSchema = type({ @@ -117,18 +113,10 @@ const handler = async ( // Our message encoding is a hex string, so we need to check that the length is even. throw new InputError("Message must be an even hex string"); } -<<<<<<< HEAD const isRecipientAContract = await sdk.utils.isContractDeployedToAddress( recipient, getProvider(destinationChainId) ); -======= - const isRecipientAContract = - (await sdk.utils.isContractDeployedToAddress( - recipientAddress, - provider - )) || true; ->>>>>>> 5797e0a6 (feat: add redis caching support for getBalance) if (!isRecipientAContract) { throw new InputError( "Recipient must be a contract when a message is provided" @@ -149,11 +137,7 @@ const handler = async ( } const balanceOfToken = await getBalance( destinationChainId, -<<<<<<< HEAD relayer, -======= - relayerAddress, ->>>>>>> 5797e0a6 (feat: add redis caching support for getBalance) destinationToken ); if (balanceOfToken.lt(amountInput)) { From 087a0ec41218c88394aba086ce65fd67d193ecbc Mon Sep 17 00:00:00 2001 From: james-a-morris Date: Thu, 14 Dec 2023 15:41:06 -0500 Subject: [PATCH 03/10] improve: change name --- api/{_imports.ts => _polyfills.ts} | 0 api/_utils.ts | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename api/{_imports.ts => _polyfills.ts} (100%) diff --git a/api/_imports.ts b/api/_polyfills.ts similarity index 100% rename from api/_imports.ts rename to api/_polyfills.ts diff --git a/api/_utils.ts b/api/_utils.ts index f18284dc6..30d73b930 100644 --- a/api/_utils.ts +++ b/api/_utils.ts @@ -1,4 +1,4 @@ -import "./_imports"; +import "./_polyfills"; import { AcceleratingDistributor__factory } from "@across-protocol/across-token/dist/typechain"; import { ERC20__factory, From 5701faa62e0dfe56cfc7ec51188a3c130ba524e5 Mon Sep 17 00:00:00 2001 From: james-a-morris Date: Thu, 14 Dec 2023 15:42:17 -0500 Subject: [PATCH 04/10] chore: change name --- api/_utils.ts | 2 +- api/limits.ts | 8 ++++---- api/suggested-fees.ts | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/api/_utils.ts b/api/_utils.ts index 30d73b930..1db94a4a6 100644 --- a/api/_utils.ts +++ b/api/_utils.ts @@ -621,7 +621,7 @@ export const isRouteEnabled = ( * @param token The valid ERC20 token address on the given `chainId`. * @returns A promise that resolves to the BigNumber of the balance */ -export const getBalance = async ( +export const getCachedBalance = async ( chainId: string | number, account: string, token: string diff --git a/api/limits.ts b/api/limits.ts index 5211d114f..cb818b4cf 100644 --- a/api/limits.ts +++ b/api/limits.ts @@ -29,7 +29,7 @@ import { getProvider, HUB_POOL_CHAIN_ID, ENABLED_ROUTES, - getBalance, + getCachedBalance, getDefaultRelayerAddress, sendResponse, } from "./_utils"; @@ -165,19 +165,19 @@ const handler = async ( hubPool.callStatic.multicall(multicallInput, { blockTag: BLOCK_TAG_LAG }), Promise.all( fullRelayers.map((relayer) => - getBalance(destinationChainId!, destinationToken, relayer) + getCachedBalance(destinationChainId!, destinationToken, relayer) ) ), Promise.all( transferRestrictedRelayers.map((relayer) => - getBalance(destinationChainId!, destinationToken, relayer) + getCachedBalance(destinationChainId!, destinationToken, relayer) ) ), Promise.all( fullRelayers.map((relayer) => destinationChainId === "1" ? ethers.BigNumber.from("0") - : getBalance("1", l1Token, relayer) + : getCachedBalance("1", l1Token, relayer) ) ), ]); diff --git a/api/suggested-fees.ts b/api/suggested-fees.ts index f276de7b9..dbfe10d90 100644 --- a/api/suggested-fees.ts +++ b/api/suggested-fees.ts @@ -30,7 +30,7 @@ import { ENABLED_ROUTES, getSpokePoolAddress, getDefaultRelayerAddress, - getBalance, + getCachedBalance, } from "./_utils"; const SuggestedFeesQueryParamsSchema = type({ @@ -135,7 +135,7 @@ const handler = async ( `Could not resolve token address on ${destinationChainId} for ${l1Token}` ); } - const balanceOfToken = await getBalance( + const balanceOfToken = await getCachedBalance( destinationChainId, relayer, destinationToken From 83bd8b82122fb89443d29a26488e1ed5c19120b5 Mon Sep 17 00:00:00 2001 From: james-a-morris Date: Thu, 14 Dec 2023 15:44:00 -0500 Subject: [PATCH 05/10] improve: bump lock --- yarn.lock | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/yarn.lock b/yarn.lock index 09c37b3dd..fbdd9727f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -21715,6 +21715,13 @@ node-fetch-native@^1.4.0: resolved "https://registry.yarnpkg.com/node-fetch-native/-/node-fetch-native-1.4.1.tgz#5a336e55b4e1b1e72b9927da09fecd2b374c9be5" integrity sha512-NsXBU0UgBxo2rQLOeWNZqS3fvflWePMECr8CoSWoSTqCqGbVVsvl9vZu1HfQicYN0g5piV9Gh8RTEvo/uP752w== +node-fetch@2, node-fetch@^2.0.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== + dependencies: + whatwg-url "^5.0.0" + node-fetch@2.6.7: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" @@ -21730,13 +21737,6 @@ node-fetch@^1.0.1, node-fetch@~1.7.1: encoding "^0.1.11" is-stream "^1.0.1" -node-fetch@^2.0.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" - integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== - dependencies: - whatwg-url "^5.0.0" - node-fetch@^2.6.0: version "2.6.12" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.12.tgz#02eb8e22074018e3d5a83016649d04df0e348fba" @@ -27953,11 +27953,6 @@ whatwg-fetch@^2.0.4: resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz#dde6a5df315f9d39991aa17621853d720b85566f" integrity sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng== -whatwg-fetch@^3.4.1: - version "3.6.19" - resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.19.tgz#caefd92ae630b91c07345537e67f8354db470973" - integrity sha512-d67JP4dHSbm2TrpFj8AbO8DnL1JXL5J9u0Kq2xW6d0TFDbCA3Muhdt8orXC22utleTVj7Prqt82baN6RBvnEgw== - whatwg-mimetype@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz#5fa1a7623867ff1af6ca3dc72ad6b8a4208beba7" From 6050bc4682652ae8b6b30702561c5e4b07eaee1b Mon Sep 17 00:00:00 2001 From: james-a-morris Date: Thu, 14 Dec 2023 16:02:22 -0500 Subject: [PATCH 06/10] improve: bump nodefetch --- package.json | 2 +- yarn.lock | 53 +++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 47 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 27dae781d..f76a2f181 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "jose": "^4.9.3", "lodash-es": "^4.17.21", "luxon": "^3.3.0", - "node-fetch": "2", + "node-fetch": "^3.3.2", "numeral": "^2.0.6", "react": "^17.0.2", "react-device-detect": "^2.2.2", diff --git a/yarn.lock b/yarn.lock index fbdd9727f..c62daf97d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13719,6 +13719,11 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" +data-uri-to-buffer@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz#d8feb2b2881e6a4f58c2e08acfd0e2834e26222e" + integrity sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A== + data-urls@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-3.0.2.tgz#9cf24a477ae22bcef5cd5f6f0bfbc1d2d3be9143" @@ -16240,6 +16245,14 @@ fecha@^4.2.0: resolved "https://registry.yarnpkg.com/fecha/-/fecha-4.2.3.tgz#4d9ccdbc61e8629b259fdca67e65891448d569fd" integrity sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw== +fetch-blob@^3.1.2, fetch-blob@^3.1.4: + version "3.2.0" + resolved "https://registry.yarnpkg.com/fetch-blob/-/fetch-blob-3.2.0.tgz#f09b8d4bbd45adc6f0c20b7e787e793e309dcce9" + integrity sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ== + dependencies: + node-domexception "^1.0.0" + web-streams-polyfill "^3.0.3" + fetch-ponyfill@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/fetch-ponyfill/-/fetch-ponyfill-4.1.0.tgz#ae3ce5f732c645eab87e4ae8793414709b239893" @@ -16537,6 +16550,13 @@ form-data@~2.3.2: combined-stream "^1.0.6" mime-types "^2.1.12" +formdata-polyfill@^4.0.10: + version "4.0.10" + resolved "https://registry.yarnpkg.com/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz#24807c31c9d402e002ab3d8c720144ceb8848423" + integrity sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g== + dependencies: + fetch-blob "^3.1.2" + forwarded@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" @@ -21695,6 +21715,11 @@ node-dir@^0.1.17: dependencies: minimatch "^3.0.2" +node-domexception@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" + integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== + node-emoji@^1.10.0: version "1.11.0" resolved "https://registry.yarnpkg.com/node-emoji/-/node-emoji-1.11.0.tgz#69a0150e6946e2f115e9d7ea4df7971e2628301c" @@ -21715,13 +21740,6 @@ node-fetch-native@^1.4.0: resolved "https://registry.yarnpkg.com/node-fetch-native/-/node-fetch-native-1.4.1.tgz#5a336e55b4e1b1e72b9927da09fecd2b374c9be5" integrity sha512-NsXBU0UgBxo2rQLOeWNZqS3fvflWePMECr8CoSWoSTqCqGbVVsvl9vZu1HfQicYN0g5piV9Gh8RTEvo/uP752w== -node-fetch@2, node-fetch@^2.0.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" - integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== - dependencies: - whatwg-url "^5.0.0" - node-fetch@2.6.7: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" @@ -21737,6 +21755,13 @@ node-fetch@^1.0.1, node-fetch@~1.7.1: encoding "^0.1.11" is-stream "^1.0.1" +node-fetch@^2.0.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== + dependencies: + whatwg-url "^5.0.0" + node-fetch@^2.6.0: version "2.6.12" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.12.tgz#02eb8e22074018e3d5a83016649d04df0e348fba" @@ -21751,6 +21776,15 @@ node-fetch@^2.6.1, node-fetch@^2.6.7: dependencies: whatwg-url "^5.0.0" +node-fetch@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.3.2.tgz#d1e889bacdf733b4ff3b2b243eb7a12866a0b78b" + integrity sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA== + dependencies: + data-uri-to-buffer "^4.0.0" + fetch-blob "^3.1.4" + formdata-polyfill "^4.0.10" + node-forge@^0.10.0: version "0.10.0" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3" @@ -27190,6 +27224,11 @@ web-encoding@^1.0.2, web-encoding@^1.0.6: optionalDependencies: "@zxing/text-encoding" "0.9.0" +web-streams-polyfill@^3.0.3: + version "3.2.1" + resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz#71c2718c52b45fd49dbeee88634b3a60ceab42a6" + integrity sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q== + web3-bzz@1.7.4: version "1.7.4" resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.7.4.tgz#9419e606e38a9777443d4ce40506ebd796e06075" From dcf535b4b57021faa2a7b1d9604e8f25bcb95a12 Mon Sep 17 00:00:00 2001 From: james-a-morris Date: Fri, 15 Dec 2023 15:54:18 -0500 Subject: [PATCH 07/10] fix: resolve VC --- api/_polyfills.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/api/_polyfills.ts b/api/_polyfills.ts index a1b1bcd66..591539476 100644 --- a/api/_polyfills.ts +++ b/api/_polyfills.ts @@ -3,3 +3,5 @@ import * as fetch from "node-fetch"; if (!globalThis.fetch) { (globalThis as any).fetch = fetch; } + +export {}; From 2661210fb067573cc2fd0956eb701a3193675b3c Mon Sep 17 00:00:00 2001 From: james-a-morris Date: Fri, 15 Dec 2023 15:56:01 -0500 Subject: [PATCH 08/10] fix: resolve VC --- api/_utils.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/api/_utils.ts b/api/_utils.ts index 1db94a4a6..b7d6bd70c 100644 --- a/api/_utils.ts +++ b/api/_utils.ts @@ -1,4 +1,7 @@ -import "./_polyfills"; +// _POLYFILLS MUST BE IMPORTED FIRST +// eslint-disable-next-line @typescript-eslint/no-unused-vars +import * as _pFill from "./_polyfills"; + import { AcceleratingDistributor__factory } from "@across-protocol/across-token/dist/typechain"; import { ERC20__factory, From cdd79b3b458b34646fb38bfb1a4d81d7b7410872 Mon Sep 17 00:00:00 2001 From: james-a-morris Date: Fri, 15 Dec 2023 15:57:11 -0500 Subject: [PATCH 09/10] docs: add comments --- api/_polyfills.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/api/_polyfills.ts b/api/_polyfills.ts index 591539476..3ca5155b4 100644 --- a/api/_polyfills.ts +++ b/api/_polyfills.ts @@ -1,5 +1,6 @@ import * as fetch from "node-fetch"; +// Required for @vercel/kv if (!globalThis.fetch) { (globalThis as any).fetch = fetch; } From 4b9ebc1ddfc71d896750999d5b10f8210aa60fca Mon Sep 17 00:00:00 2001 From: james-a-morris Date: Tue, 19 Dec 2023 09:23:33 -0500 Subject: [PATCH 10/10] improve: catch error if cache balance fails --- api/_utils.ts | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/api/_utils.ts b/api/_utils.ts index b7d6bd70c..e6c44d15b 100644 --- a/api/_utils.ts +++ b/api/_utils.ts @@ -246,6 +246,7 @@ export const getTokenDetails = async ( }; export class InputError extends Error {} +export class ServerError extends Error {} /** * Resolves an Infura provider given the name of the ETH network @@ -640,13 +641,17 @@ export const getCachedBalance = async ( getProvider(Number(chainId)), BLOCK_TAG_LAG // We should do this for consistency ); - await kv.set(key, balance.toString(), { - ex: 60 * 5, // 5 minutes - }); - getLogger().debug({ - at: "_utils#getBalance", - message: `Cached balance for ${key}: ${balance}`, - }); + try { + await kv.set(key, balance.toString(), { + ex: 60 * 5, // 5 minutes + }); + getLogger().debug({ + at: "_utils#getBalance", + message: `Cached balance for ${key}: ${balance}`, + }); + } catch (_err) { + throw new ServerError(); + } return balance; } };