From 4d9cac4299cd07621cca360ab9d4ecaaffa847c0 Mon Sep 17 00:00:00 2001 From: Antonio Salazar Cardozo Date: Tue, 22 Feb 2022 14:48:03 -0500 Subject: [PATCH 01/10] Move asset similarity and closeness into background/assets This functionality is useful more broadly than the assets slice. --- background/assets.ts | 76 +++++++++++++++++++++++++++++ background/redux-slices/assets.ts | 79 ++----------------------------- 2 files changed, 80 insertions(+), 75 deletions(-) diff --git a/background/assets.ts b/background/assets.ts index 3d7eaa0931..d1f89861ff 100644 --- a/background/assets.ts +++ b/background/assets.ts @@ -344,3 +344,79 @@ export function assetAmountToDesiredDecimals( return fromFixedPoint(amount, decimals, desiredDecimals) } + +/** + * Use heuristics to score two assets based on their metadata similarity. The + * higher the score, the more likely the asset metadata refers to the same + * asset. + * + * @param a - the first asset + * @param b - the second asset + * @return an integer score >= 0 + */ +export function scoreAssetSimilarity(a: AnyAsset, b: AnyAsset): number { + let score = 0 + if (a.symbol === b.symbol) { + score += 1 + } + if (a.name === b.name) { + score += 1 + } + if ("decimals" in a && "decimals" in b) { + if (a.decimals === b.decimals) { + score += 1 + } else { + score -= 1 + } + } else if ("decimals" in a || "decimals" in b) { + score -= 1 + } + if ("homeNetwork" in a && "homeNetwork" in b) { + if ( + a.homeNetwork.name === b.homeNetwork.name && + a.homeNetwork.chainID === b.homeNetwork.chainID + ) { + score += 1 + } else { + score -= 1 + } + } else if ("homeNetwork" in a || "homeNetwork" in b) { + score -= 1 + } + return score +} + +/** + * Score a set of assets by similarity to a search asset, returning the most + * similiar asset to the search asset as long as it is above a base similiarity + * score, or null. + * + * @see scoreAssetSimilarity The way assets are checked for similarity. + * + * @param assetToFind The asset we're trying to find. + * @param assets The array of assets in which to search for `assetToFind`. + * @param minimumSimilarityScore The minimum similarity score to consider as a + * match. + */ +export function findClosestAssetIndex( + assetToFind: AnyAsset, + assets: AnyAsset[], + minimumSimilarityScore = 2 +): number | undefined { + const [bestScore, index] = assets.reduce( + ([runningScore, runningScoreIndex], asset, i) => { + const score = scoreAssetSimilarity(assetToFind, asset) + if (score > runningScore) { + return [score, i] + } + return [runningScore, runningScoreIndex] + }, + [0, -1] + ) + + if (bestScore >= minimumSimilarityScore && index >= 0) { + return index + } + + return undefined +} diff --git a/background/redux-slices/assets.ts b/background/redux-slices/assets.ts index 455be41adc..ed5ab709ef 100644 --- a/background/redux-slices/assets.ts +++ b/background/redux-slices/assets.ts @@ -1,5 +1,5 @@ import { createSelector, createSlice } from "@reduxjs/toolkit" -import { AnyAsset, PricePoint } from "../assets" +import { AnyAsset, findClosestAssetIndex, PricePoint } from "../assets" import { normalizeEVMAddress } from "../lib/utils" type SingleAssetState = AnyAsset & { @@ -13,77 +13,6 @@ export type AssetsState = SingleAssetState[] export const initialState = [] as AssetsState -/* - * Use heuristics to score two assets based on their metadata similarity. The - * higher the score, the more likely the asset metadata refers to the same - * asset. - * - * @param a - the first asset - * @param b - the second asset - * @returns an integer score >= 0 - */ -function scoreAssetSimilarity(a: AnyAsset, b: AnyAsset): number { - let score = 0 - if (a.symbol === b.symbol) { - score += 1 - } - if (a.name === b.name) { - score += 1 - } - if ("decimals" in a && "decimals" in b) { - if (a.decimals === b.decimals) { - score += 1 - } else { - score -= 1 - } - } else if ("decimals" in a || "decimals" in b) { - score -= 1 - } - if ("homeNetwork" in a && "homeNetwork" in b) { - if ( - a.homeNetwork.name === b.homeNetwork.name && - a.homeNetwork.chainID === b.homeNetwork.chainID - ) { - score += 1 - } else { - score -= 1 - } - } else if ("homeNetwork" in a || "homeNetwork" in b) { - score -= 1 - } - return score -} - -/* - * Score all assets by similarity, returning the most similiar asset as long as - * it is above a base similiarity score, or null. - * - * @param baseAsset - the asset we're trying to find - * @param assets - an array of assets to sort - */ -function findClosestAsset( - baseAsset: AnyAsset, - assets: AnyAsset[], - minScore = 2 -): number | null { - const [bestScore, index] = assets.reduce( - ([runningScore, runningScoreIndex], asset, i) => { - const score = scoreAssetSimilarity(baseAsset, asset) - if (score > runningScore) { - return [score, i] - } - return [runningScore, runningScoreIndex] - }, - [0, -1] as [number, number] - ) - - if (bestScore >= minScore && index >= 0) { - return index - } - - return null -} - function prunePrices(prices: PricePoint[]): PricePoint[] { // TODO filter prices to daily in the past week, weekly in the past month, monthly in the past year const pricesToSort = prices.map<[number, PricePoint]>((pp) => [pp.time, pp]) @@ -118,9 +47,9 @@ function recentPricesFromArray( return pricesToSort .map((r) => r[1] as PricePoint) .reduce((agg: SingleAssetState["recentPrices"], pp: PricePoint) => { - const pricedAssetIndex = findClosestAsset(baseAsset, pp.pair) + const pricedAssetIndex = findClosestAssetIndex(baseAsset, pp.pair) if (pricedAssetIndex !== null) { - const pricedAsset = pp.pair[+(pricedAssetIndex === 0)] + const pricedAsset = pp.pair[pricedAssetIndex === 0 ? 0 : 1] const newAgg = { ...agg, } @@ -186,7 +115,7 @@ const assetsSlice = createSlice({ ) => { pricePoint.pair.forEach((pricedAsset) => { // find the asset metadata - const index = findClosestAsset(pricedAsset, [ + const index = findClosestAssetIndex(pricedAsset, [ ...immerState, ] as AnyAsset[]) if (index !== null) { From 4d6b8702ab84ae2ab5ba29d51ffc390eaa73fbb3 Mon Sep 17 00:00:00 2001 From: Antonio Salazar Cardozo Date: Tue, 22 Feb 2022 16:05:55 -0500 Subject: [PATCH 02/10] Add lib/asset-similarity This absorbs asset similarity scoring and finding of closest assets, but also adds asset merging and a function generate prioritized asset similarity keys, which can be used for more efficient asset correlation vs pairwise asset similarity checks. --- background/assets.ts | 76 ------------------- background/lib/asset-similarity.ts | 115 +++++++++++++++++++++++++++++ background/redux-slices/assets.ts | 5 +- 3 files changed, 118 insertions(+), 78 deletions(-) create mode 100644 background/lib/asset-similarity.ts diff --git a/background/assets.ts b/background/assets.ts index d1f89861ff..3d7eaa0931 100644 --- a/background/assets.ts +++ b/background/assets.ts @@ -344,79 +344,3 @@ export function assetAmountToDesiredDecimals( return fromFixedPoint(amount, decimals, desiredDecimals) } - -/** - * Use heuristics to score two assets based on their metadata similarity. The - * higher the score, the more likely the asset metadata refers to the same - * asset. - * - * @param a - the first asset - * @param b - the second asset - * @return an integer score >= 0 - */ -export function scoreAssetSimilarity(a: AnyAsset, b: AnyAsset): number { - let score = 0 - if (a.symbol === b.symbol) { - score += 1 - } - if (a.name === b.name) { - score += 1 - } - if ("decimals" in a && "decimals" in b) { - if (a.decimals === b.decimals) { - score += 1 - } else { - score -= 1 - } - } else if ("decimals" in a || "decimals" in b) { - score -= 1 - } - if ("homeNetwork" in a && "homeNetwork" in b) { - if ( - a.homeNetwork.name === b.homeNetwork.name && - a.homeNetwork.chainID === b.homeNetwork.chainID - ) { - score += 1 - } else { - score -= 1 - } - } else if ("homeNetwork" in a || "homeNetwork" in b) { - score -= 1 - } - return score -} - -/** - * Score a set of assets by similarity to a search asset, returning the most - * similiar asset to the search asset as long as it is above a base similiarity - * score, or null. - * - * @see scoreAssetSimilarity The way assets are checked for similarity. - * - * @param assetToFind The asset we're trying to find. - * @param assets The array of assets in which to search for `assetToFind`. - * @param minimumSimilarityScore The minimum similarity score to consider as a - * match. - */ -export function findClosestAssetIndex( - assetToFind: AnyAsset, - assets: AnyAsset[], - minimumSimilarityScore = 2 -): number | undefined { - const [bestScore, index] = assets.reduce( - ([runningScore, runningScoreIndex], asset, i) => { - const score = scoreAssetSimilarity(assetToFind, asset) - if (score > runningScore) { - return [score, i] - } - return [runningScore, runningScoreIndex] - }, - [0, -1] - ) - - if (bestScore >= minimumSimilarityScore && index >= 0) { - return index - } - - return undefined -} diff --git a/background/lib/asset-similarity.ts b/background/lib/asset-similarity.ts new file mode 100644 index 0000000000..4bcedfd5f8 --- /dev/null +++ b/background/lib/asset-similarity.ts @@ -0,0 +1,115 @@ +import { AnyAsset, isSmartContractFungibleAsset } from "../assets" +import { normalizeEVMAddress } from "./utils" + +/** + * Use heuristics to score two assets based on their metadata similarity. The + * higher the score, the more likely the asset metadata refers to the same + * asset. + * + * @param a - the first asset + * @param b - the second asset + * @return an integer score >= 0 + */ +export function scoreAssetSimilarity(a: AnyAsset, b: AnyAsset): number { + let score = 0 + if (a.symbol === b.symbol) { + score += 1 + } + if (a.name === b.name) { + score += 1 + } + if ("decimals" in a && "decimals" in b) { + if (a.decimals === b.decimals) { + score += 1 + } else { + score -= 1 + } + } else if ("decimals" in a || "decimals" in b) { + score -= 1 + } + if ("homeNetwork" in a && "homeNetwork" in b) { + const sameNetwork = + a.homeNetwork.name === b.homeNetwork.name && + a.homeNetwork.chainID === b.homeNetwork.chainID + if (sameNetwork) { + score += 1 + } else { + score -= 1 + } + } else if ("homeNetwork" in a || "homeNetwork" in b) { + score -= 1 + } + return score +} + +/** + * Returns a prioritized list of similarity keys, which are strings that can be + * used to rapidly correlate assets. All similarity keys should be further + * checked using {@link assetsSufficientlySimilar}, as a similarity key match + * is designed to narrow the field rather than guarantee asset sameness. + */ +export function prioritizedAssetSimilarityKeys(asset: AnyAsset): string[] { + let similarityKeys: string[] = [] + + if (isSmartContractFungibleAsset(asset)) { + const normalizedContractAddressAndNetwork = `${normalizeEVMAddress( + asset.contractAddress + )}-${asset.homeNetwork.chainID}` + + similarityKeys = [...similarityKeys, normalizedContractAddressAndNetwork] + } + + return [...similarityKeys, asset.symbol] +} + +/** + * Score a set of assets by similarity to a search asset, returning the most + * similiar asset to the search asset as long as it is above a base similiarity + * score, or null. + * + * @see scoreAssetSimilarity The way asset similarity is computed. + * + * @param assetToFind The asset we're trying to find. + * @param assets The array of assets in which to search for `assetToFind`. + * @param minimumSimilarityScore The minimum similarity score to consider as a + * match. + */ +export function findClosestAssetIndex( + assetToFind: AnyAsset, + assets: AnyAsset[], + minimumSimilarityScore = 2 +): number | undefined { + const [bestScore, index] = assets.reduce( + ([runningScore, runningScoreIndex], asset, i) => { + const score = scoreAssetSimilarity(assetToFind, asset) + if (score > runningScore) { + return [score, i] + } + return [runningScore, runningScoreIndex] + }, + [0, -1] + ) + + if (bestScore >= minimumSimilarityScore && index >= 0) { + return index + } + + return undefined +} + +/** + * Merges the information about two assets. Mostly focused on merging metadata. + */ +export function mergeAssets(asset1: AnyAsset, asset2: AnyAsset): AnyAsset { + return { + ...asset1, + metadata: { + ...asset1.metadata, + ...asset2.metadata, + tokenLists: + asset1.metadata?.tokenLists?.concat( + asset2.metadata?.tokenLists ?? [] + ) ?? [], + }, + } +} diff --git a/background/redux-slices/assets.ts b/background/redux-slices/assets.ts index ed5ab709ef..c25c6ae07c 100644 --- a/background/redux-slices/assets.ts +++ b/background/redux-slices/assets.ts @@ -1,5 +1,6 @@ import { createSelector, createSlice } from "@reduxjs/toolkit" -import { AnyAsset, findClosestAssetIndex, PricePoint } from "../assets" +import { AnyAsset, PricePoint } from "../assets" +import { findClosestAssetIndex } from "../lib/asset-similarity" import { normalizeEVMAddress } from "../lib/utils" type SingleAssetState = AnyAsset & { @@ -118,7 +119,7 @@ const assetsSlice = createSlice({ const index = findClosestAssetIndex(pricedAsset, [ ...immerState, ] as AnyAsset[]) - if (index !== null) { + if (typeof index !== "undefined") { // append to longer-running prices const prices = prunePrices( [...immerState[index].prices].concat([pricePoint]) From 512de13850201d17513de46331e7f4ccc803be1d Mon Sep 17 00:00:00 2001 From: Antonio Salazar Cardozo Date: Tue, 22 Feb 2022 15:44:17 -0500 Subject: [PATCH 03/10] Rework token list asset merging to use similarity keys This opens up space for assets with similarity keys that don't conform to standard EVM expectations, or that can benefit from additional specificity on other chains. --- background/lib/tokenList.ts | 106 +++++++++++++++--------------------- 1 file changed, 43 insertions(+), 63 deletions(-) diff --git a/background/lib/tokenList.ts b/background/lib/tokenList.ts index 6008b94c11..b8c6a8fd29 100644 --- a/background/lib/tokenList.ts +++ b/background/lib/tokenList.ts @@ -1,14 +1,16 @@ import { TokenList } from "@uniswap/token-lists" -import { normalizeEVMAddress } from "./utils" import { FungibleAsset, - isSmartContractFungibleAsset, SmartContractFungibleAsset, TokenListAndReference, } from "../assets" import { isValidUniswapTokenListResponse } from "./validate" import { EVMNetwork } from "../networks" +import { + findClosestAssetIndex, + prioritizedAssetSimilarityKeys, +} from "./asset-similarity" export async function fetchAndValidateTokenList( url: string @@ -66,89 +68,67 @@ function tokenListToFungibleAssetsForNetwork( /** * Merges the given asset lists into a single deduplicated array. + * + * Note that currently, two smart contract assets that are the same but don't + * share a contract address (e.g., a token A that points to a contract address + * and a token A that points to a proxy A's contract address) will not be + * considered the same for merging purposes. */ export function mergeAssets( ...assetLists: T[][] ): T[] { function tokenReducer( - seenAssetsBy: { - contractAddressAndNetwork: { - [contractAddressAndNetwork: string]: SmartContractFungibleAsset - } - symbol: { [symbol: string]: T } + seenAssetsBySimilarityKey: { + [similarityKey: string]: T[] }, asset: T ) { - const updatedAssetsBy = { - contractAddressAndNetwork: { ...seenAssetsBy.contractAddressAndNetwork }, - symbol: { ...seenAssetsBy.symbol }, - } + const updatedSeenAssetsBySimilarityKey = { ...seenAssetsBySimilarityKey } - if (isSmartContractFungibleAsset(asset)) { - const normalizedContractAddressAndNetwork = - `${normalizeEVMAddress(asset.contractAddress)}-${ - asset.homeNetwork.chainID - }` ?? asset.homeNetwork.name - const existingAsset = - updatedAssetsBy.contractAddressAndNetwork[ - normalizedContractAddressAndNetwork - ] - - if (typeof existingAsset !== "undefined") { - updatedAssetsBy.contractAddressAndNetwork[ - normalizedContractAddressAndNetwork - ] = { - ...existingAsset, - metadata: { - ...existingAsset.metadata, - ...asset.metadata, - tokenLists: - existingAsset.metadata?.tokenLists?.concat( - asset.metadata?.tokenLists ?? [] - ) ?? [], - }, - } - } else { - updatedAssetsBy.contractAddressAndNetwork[ - normalizedContractAddressAndNetwork - ] = asset - } - } else if (asset.symbol in updatedAssetsBy.symbol) { - const original = updatedAssetsBy.symbol[asset.symbol] - updatedAssetsBy.symbol[asset.symbol] = { - ...original, + const similarityKeys = prioritizedAssetSimilarityKeys(asset) + + // For now, only use the highest-priority similarity key with no fallback. + const referenceKey = similarityKeys[0] + // Initialize if needed. + updatedSeenAssetsBySimilarityKey[referenceKey] ??= [] + + // For each key, determine where a close asset match exists. + const matchingAssetIndex = findClosestAssetIndex( + asset, + seenAssetsBySimilarityKey[referenceKey] + ) + + if (typeof matchingAssetIndex !== "undefined") { + // Merge the matching asset with this new one. + const matchingAsset = + updatedSeenAssetsBySimilarityKey[referenceKey][matchingAssetIndex] + + updatedSeenAssetsBySimilarityKey[referenceKey][matchingAssetIndex] = { + ...matchingAsset, metadata: { - ...original.metadata, + ...matchingAsset.metadata, ...asset.metadata, tokenLists: - original.metadata?.tokenLists?.concat( + matchingAsset.metadata?.tokenLists?.concat( asset.metadata?.tokenLists ?? [] ) ?? [], }, } } else { - updatedAssetsBy.symbol[asset.symbol] = asset + updatedSeenAssetsBySimilarityKey[referenceKey].push(asset) } - return updatedAssetsBy + return updatedSeenAssetsBySimilarityKey } - const mergedAssetsBy = assetLists.flat().reduce(tokenReducer, { - contractAddressAndNetwork: {}, - symbol: {}, - }) - const mergedAssets = Object.values(mergedAssetsBy.symbol).concat( - // Because the inputs to the function conform to T[], if T is not a subtype - // of SmartContractFungibleAsset, this will be an empty array. As such, we - // can safely do this cast. - Object.values(mergedAssetsBy.contractAddressAndNetwork) as unknown as T[] - ) + const mergedAssetsBy = assetLists.flat().reduce(tokenReducer, {}) + const mergedAssets = Object.values(mergedAssetsBy).flat() - return mergedAssets.sort((a, b) => - (a.metadata?.tokenLists?.length || 0) > - (b.metadata?.tokenLists?.length || 0) - ? 1 - : -1 + // Sort the merged assets by the number of token lists they appear in. + return mergedAssets.sort( + (a, b) => + (a.metadata?.tokenLists?.length || 0) - + (b.metadata?.tokenLists?.length || 0) ) } From aeab5555fa6ceadd46b1c5d25efa0bb8cdf7cdb7 Mon Sep 17 00:00:00 2001 From: Antonio Salazar Cardozo Date: Tue, 22 Feb 2022 15:46:55 -0500 Subject: [PATCH 04/10] tokenList.ts -> token-lists.ts Not sure why this was ever camel-cased, but it shouldn't be. --- background/lib/erc20.ts | 4 ++-- background/lib/{tokenList.ts => token-lists.ts} | 0 background/services/indexing/index.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename background/lib/{tokenList.ts => token-lists.ts} (100%) diff --git a/background/lib/erc20.ts b/background/lib/erc20.ts index 7f2b555905..862d38519e 100644 --- a/background/lib/erc20.ts +++ b/background/lib/erc20.ts @@ -1,12 +1,12 @@ import { AlchemyProvider, BaseProvider } from "@ethersproject/providers" -import { BigNumber, ethers, logger } from "ethers" +import { BigNumber, ethers } from "ethers" import { EventFragment, Fragment, FunctionFragment, TransactionDescription, } from "ethers/lib/utils" -import { getTokenBalances, getTokenMetadata } from "./alchemy" +import { getTokenBalances } from "./alchemy" import { AccountBalance, AddressOnNetwork } from "../accounts" import { SmartContractFungibleAsset } from "../assets" import { EVMLog } from "../networks" diff --git a/background/lib/tokenList.ts b/background/lib/token-lists.ts similarity index 100% rename from background/lib/tokenList.ts rename to background/lib/token-lists.ts diff --git a/background/services/indexing/index.ts b/background/services/indexing/index.ts index 2165c3561f..900b575ca8 100644 --- a/background/services/indexing/index.ts +++ b/background/services/indexing/index.ts @@ -19,7 +19,7 @@ import { fetchAndValidateTokenList, mergeAssets, networkAssetsFromLists, -} from "../../lib/tokenList" +} from "../../lib/token-lists" import PreferenceService from "../preferences" import ChainService from "../chain" import { ServiceCreatorFunction, ServiceLifecycleEvents } from "../types" From f053a9d9dc31f8eeddaceb0903a75f3d9dfa2b92 Mon Sep 17 00:00:00 2001 From: Antonio Salazar Cardozo Date: Thu, 24 Feb 2022 15:43:35 -0500 Subject: [PATCH 05/10] Resolve closest asset index against latest assets This was matching against an outdated list. --- background/lib/token-lists.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/background/lib/token-lists.ts b/background/lib/token-lists.ts index b8c6a8fd29..a20ec14180 100644 --- a/background/lib/token-lists.ts +++ b/background/lib/token-lists.ts @@ -95,7 +95,7 @@ export function mergeAssets( // For each key, determine where a close asset match exists. const matchingAssetIndex = findClosestAssetIndex( asset, - seenAssetsBySimilarityKey[referenceKey] + updatedSeenAssetsBySimilarityKey[referenceKey] ) if (typeof matchingAssetIndex !== "undefined") { From b69c2a06cfc0e75cbccb901b3fe884d4c1f075a9 Mon Sep 17 00:00:00 2001 From: Antonio Salazar Cardozo Date: Thu, 24 Feb 2022 15:47:13 -0500 Subject: [PATCH 06/10] Fix asset pruning Due to a nomenclature issue, the priced vs base asset in the price pair were reversed, and the results were likewise reversed, leading to price lookup issues. --- background/redux-slices/assets.ts | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/background/redux-slices/assets.ts b/background/redux-slices/assets.ts index c25c6ae07c..0225def0fe 100644 --- a/background/redux-slices/assets.ts +++ b/background/redux-slices/assets.ts @@ -43,18 +43,18 @@ function recentPricesFromArray( baseAsset: AnyAsset, prices: PricePoint[] ): SingleAssetState["recentPrices"] { - const pricesToSort = prices.map((pp) => [pp.time, pp]) + const pricesToSort = prices.map((pp) => [pp.time, pp] as const) pricesToSort.sort() return pricesToSort - .map((r) => r[1] as PricePoint) + .map((r) => r[1]) .reduce((agg: SingleAssetState["recentPrices"], pp: PricePoint) => { - const pricedAssetIndex = findClosestAssetIndex(baseAsset, pp.pair) - if (pricedAssetIndex !== null) { - const pricedAsset = pp.pair[pricedAssetIndex === 0 ? 0 : 1] + const baseAssetIndex = findClosestAssetIndex(baseAsset, pp.pair) + if (baseAssetIndex !== null) { + const priceAsset = pp.pair[baseAssetIndex === 0 ? 1 : 0] const newAgg = { ...agg, } - newAgg[pricedAsset.symbol] = pp + newAgg[priceAsset.symbol] = pp return newAgg } return agg @@ -116,14 +116,10 @@ const assetsSlice = createSlice({ ) => { pricePoint.pair.forEach((pricedAsset) => { // find the asset metadata - const index = findClosestAssetIndex(pricedAsset, [ - ...immerState, - ] as AnyAsset[]) + const index = findClosestAssetIndex(pricedAsset, immerState) if (typeof index !== "undefined") { // append to longer-running prices - const prices = prunePrices( - [...immerState[index].prices].concat([pricePoint]) - ) + const prices = prunePrices([...immerState[index].prices, pricePoint]) immerState[index].prices = prices // update recent prices for easy checks by symbol immerState[index].recentPrices = recentPricesFromArray( From b62862be791a7f2915ecb42177335951a1737230 Mon Sep 17 00:00:00 2001 From: gasolin Date: Sat, 26 Feb 2022 10:37:19 +0800 Subject: [PATCH 07/10] Remove /slices in UI readme --- ui/README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/ui/README.md b/ui/README.md index b5f6e05f35..8699ba246a 100644 --- a/ui/README.md +++ b/ui/README.md @@ -50,7 +50,4 @@ by the folder they're in. /public # Static assets like fonts and images - -/slices -# Reducers and actions consolidated as files here. Interacting with the project's background.js api and using its data to populate frontend's state happens here ``` From e03efd186cbf8753d50a5786e70700610314245a Mon Sep 17 00:00:00 2001 From: Fred Date: Sat, 26 Feb 2022 22:08:41 +0800 Subject: [PATCH 08/10] warning fix and update prettier packages --- .../redux-slices/utils/contract-utils.ts | 4 +- background/services/enrichment/index.ts | 1 - background/tests/prices.test.ts | 1 - package.json | 10 +- ui/components/TabBar/TabBar.tsx | 2 +- ui/components/TopMenu/TopMenu.tsx | 2 +- ui/components/Wallet/WalletActivityList.tsx | 1 - ui/pages/DAppConnectRequest.tsx | 2 +- ui/pages/Onboarding/OnboardingVerifySeed.tsx | 2 +- .../Onboarding/OnboardingViewOnlyWallet.tsx | 2 +- yarn.lock | 236 +++++++++++------- 11 files changed, 162 insertions(+), 101 deletions(-) diff --git a/background/redux-slices/utils/contract-utils.ts b/background/redux-slices/utils/contract-utils.ts index aba3c1500a..4b8535a0aa 100644 --- a/background/redux-slices/utils/contract-utils.ts +++ b/background/redux-slices/utils/contract-utils.ts @@ -1,6 +1,6 @@ +// eslint-disable-next-line @typescript-eslint/no-unused-vars import browser from "webextension-polyfill" -import { Provider, Web3Provider } from "@ethersproject/providers" -import { INTERNAL_PORT_NAME } from "@tallyho/provider-bridge-shared" +import { Web3Provider } from "@ethersproject/providers" import TallyWindowProvider from "@tallyho/window-provider" import { Contract, ethers, ContractInterface } from "ethers" import Emittery from "emittery" diff --git a/background/services/enrichment/index.ts b/background/services/enrichment/index.ts index ea91a15287..4efbb8e30d 100644 --- a/background/services/enrichment/index.ts +++ b/background/services/enrichment/index.ts @@ -9,7 +9,6 @@ import { } from "../../networks" import { enrichAssetAmountWithDecimalValues } from "../../redux-slices/utils/asset-utils" -import { ETH } from "../../constants" import { parseERC20Tx, parseLogsForERC20Transfers } from "../../lib/erc20" import { sameEVMAddress } from "../../lib/utils" diff --git a/background/tests/prices.test.ts b/background/tests/prices.test.ts index d85c01e6e8..fc6fc2db38 100644 --- a/background/tests/prices.test.ts +++ b/background/tests/prices.test.ts @@ -1,6 +1,5 @@ // It's necessary to have an object w/ the function on it so we can use spyOn import * as ethers from "@ethersproject/web" // << THIS IS THE IMPORTANT TRICK -import { JSONSchemaType, ValidateFunction } from "ajv" import logger from "../lib/logger" import { BTC, ETH, FIAT_CURRENCIES, USD } from "../constants" diff --git a/package.json b/package.json index 6e4ac05a3c..7c3b34e590 100644 --- a/package.json +++ b/package.json @@ -82,10 +82,10 @@ "eslint-config-airbnb": "^18.2.1", "eslint-config-airbnb-base": "^14.2.1", "eslint-config-airbnb-typescript": "^14.0.0", - "eslint-config-prettier": "^8.3.0", - "eslint-plugin-import": "^2.23.4", - "eslint-plugin-jsx-a11y": "^6.4.1", - "eslint-plugin-prettier": "^3.4.0", + "eslint-config-prettier": "^8.4.0", + "eslint-plugin-import": "^2.25.4", + "eslint-plugin-jsx-a11y": "^6.5.1", + "eslint-plugin-prettier": "^4.0.0", "eslint-plugin-react": "^7.24.0", "eslint-plugin-react-hooks": "^4.2.0", "fork-ts-checker-webpack-plugin": "^6.3.2", @@ -94,7 +94,7 @@ "npm": "^7.5.6", "npm-run-all": "^4.1.5", "patch-package": "^6.4.7", - "prettier": "^2.3.2", + "prettier": "^2.5.1", "process": "^0.11.10", "size-plugin": "^2.0.2", "stream-browserify": "^3.0.0", diff --git a/ui/components/TabBar/TabBar.tsx b/ui/components/TabBar/TabBar.tsx index 25dc1b3b88..0775fa17dc 100644 --- a/ui/components/TabBar/TabBar.tsx +++ b/ui/components/TabBar/TabBar.tsx @@ -1,4 +1,4 @@ -import React, { ReactElement, useState } from "react" +import React, { ReactElement } from "react" import { useLocation } from "react-router-dom" import TabBarIcon from "./TabBarIcon" diff --git a/ui/components/TopMenu/TopMenu.tsx b/ui/components/TopMenu/TopMenu.tsx index 767aba629b..0ef81c967f 100644 --- a/ui/components/TopMenu/TopMenu.tsx +++ b/ui/components/TopMenu/TopMenu.tsx @@ -34,7 +34,7 @@ export default function TopMenu(): ReactElement { const currentAccount = useBackgroundSelector(selectCurrentAccount) const initPermissionAndOrigin = useCallback(async () => { - const { url, favIconUrl, title } = await browser.tabs + const { url } = await browser.tabs .query({ active: true, lastFocusedWindow: true, diff --git a/ui/components/Wallet/WalletActivityList.tsx b/ui/components/Wallet/WalletActivityList.tsx index 3ccf62d235..d63cdebf8f 100644 --- a/ui/components/Wallet/WalletActivityList.tsx +++ b/ui/components/Wallet/WalletActivityList.tsx @@ -7,7 +7,6 @@ import { import { ActivityItem } from "@tallyho/tally-background/redux-slices/activities" import { useBackgroundDispatch, useBackgroundSelector } from "../../hooks" import SharedSlideUpMenu from "../Shared/SharedSlideUpMenu" -import SharedLoadingSpinner from "../Shared/SharedLoadingSpinner" import WalletActivityDetails from "./WalletActivityDetails" import WalletActivityListItem from "./WalletActivityListItem" diff --git a/ui/pages/DAppConnectRequest.tsx b/ui/pages/DAppConnectRequest.tsx index f26982c2db..76aa5c5471 100644 --- a/ui/pages/DAppConnectRequest.tsx +++ b/ui/pages/DAppConnectRequest.tsx @@ -64,7 +64,7 @@ export default function DAppConnectRequest(): ReactElement { const dispatch = useBackgroundDispatch() useEffect(() => { - window.onbeforeunload = (ev) => { + window.onbeforeunload = () => { if (typeof permission !== "undefined") { dispatch( denyOrRevokePermission({ diff --git a/ui/pages/Onboarding/OnboardingVerifySeed.tsx b/ui/pages/Onboarding/OnboardingVerifySeed.tsx index 0f623179de..a7615c2760 100644 --- a/ui/pages/Onboarding/OnboardingVerifySeed.tsx +++ b/ui/pages/Onboarding/OnboardingVerifySeed.tsx @@ -148,7 +148,7 @@ export default function OnboardingVerifySeed(): ReactElement {
- - - -
- {isSelected.slice(posOne, posTwo).map((item, index) => ( + {isSelected.slice(posOne, posTwo).map((item) => (
Date: Sat, 26 Feb 2022 23:06:45 +0800 Subject: [PATCH 09/10] support build edge extension --- README.md | 16 +++++++++------- webpack.config.ts | 2 +- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 996979bc30..9bc1c38305 100644 --- a/README.md +++ b/README.md @@ -40,9 +40,9 @@ $ yarn start # start a continuous webpack build that will auto-update with chang Once the build is running, you can install the extension in your browser of choice: - [Firefox instructions](https://extensionworkshop.com/documentation/develop/temporary-installation-in-firefox/) -- [Chrome, Brave, and Opera instructions](https://developer.chrome.com/docs/extensions/mv3/getstarted/#manifest) +- [Chrome, Brave, Edge, and Opera instructions](https://developer.chrome.com/docs/extensions/mv3/getstarted/#manifest) - Note that these instructions are for Chrome, but substituting - `brave://extensions` or `opera://extensions` for `chrome://extensions` + `brave://extensions` or `edge://extensions` or `opera://extensions` for `chrome://extensions` depending on browser should get you to the same buttons. Extension bundles for each browser are in `dist/`. @@ -291,11 +291,13 @@ src/ # extension source files dist/ # output directory for builds brave/ # browser-specific - firefox/ # build - chrome/ # directories - brave.zip # browser-specific - firefox.zip # production - chrome.zip # bundles + chrome/ # build + edge/ # directories + firefox/ + brave.zip # browser-specific + chrome.zip # production + edge.zip # bundles + firefox.zip build-utils/ # build-related helpers, used in webpack.config.js *.js diff --git a/webpack.config.ts b/webpack.config.ts index 92264f576d..193482700d 100644 --- a/webpack.config.ts +++ b/webpack.config.ts @@ -15,7 +15,7 @@ import ForkTsCheckerWebpackPlugin from "fork-ts-checker-webpack-plugin" import { GitRevisionPlugin } from "git-revision-webpack-plugin" import WebExtensionArchivePlugin from "./build-utils/web-extension-archive-webpack-plugin" -const supportedBrowsers = ["firefox", "brave", "opera", "chrome"] +const supportedBrowsers = ["brave", "chrome", "edge", "firefox", "opera"] const gitRevisionPlugin = new GitRevisionPlugin() From 6d03521a255112e248b1521e7af69e640b048070 Mon Sep 17 00:00:00 2001 From: Fred Date: Sun, 27 Feb 2022 14:16:30 +0800 Subject: [PATCH 10/10] remove browser import --- background/redux-slices/utils/contract-utils.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/background/redux-slices/utils/contract-utils.ts b/background/redux-slices/utils/contract-utils.ts index 4b8535a0aa..1a9040f556 100644 --- a/background/redux-slices/utils/contract-utils.ts +++ b/background/redux-slices/utils/contract-utils.ts @@ -1,5 +1,3 @@ -// eslint-disable-next-line @typescript-eslint/no-unused-vars -import browser from "webextension-polyfill" import { Web3Provider } from "@ethersproject/providers" import TallyWindowProvider from "@tallyho/window-provider" import { Contract, ethers, ContractInterface } from "ethers"