-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Expand file tree
/
Copy pathindex.ts
More file actions
92 lines (80 loc) · 3.13 KB
/
Copy pathindex.ts
File metadata and controls
92 lines (80 loc) · 3.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import { Nft, NftControllerState } from '@metamask/assets-controllers';
import { Hex } from '@metamask/utils';
import { isEqual } from 'lodash';
import { getIntlNumberFormatter } from '../intl';
export const formatWithThreshold = (
amount: number | null,
threshold: number,
locale: string,
options: Intl.NumberFormatOptions,
): string => {
if (amount === null || isNaN(amount)) {
return '';
}
// Ensures that if we are using currency, we are using the narrow symbol to match existing currencies.
// E.g. instead of US$xx.yy we show $xx.yy
if (options.currency && !options.currencyDisplay) {
options.currencyDisplay = 'narrowSymbol';
}
if (amount === 0) {
return getIntlNumberFormatter(locale, options).format(0);
}
return amount < threshold
? `<${getIntlNumberFormatter(locale, options).format(threshold)}`
: getIntlNumberFormatter(locale, options).format(amount);
};
type AccountNfts = NftControllerState['allNfts'][string]; // Type for NFTs of a single account
const getChainEntries = (state: AccountNfts): [Hex, Nft[]][] =>
Object.entries(state) as [Hex, Nft[]][];
const isMatchingNft = (nft1: Nft, nft2: Nft) =>
nft1.address === nft2.address && nft1.tokenId === nft2.tokenId;
/**
* Compares two NFT states for a single account and returns newly detected NFTs
* @param previousState - Previous state of NFTs grouped by chainId for a single account
* @param newState - New state of NFTs grouped by chainId for a single account
* @returns Array of newly detected NFTs with their respective chainIds
*/
export const compareNftStates = (
previousState?: AccountNfts,
newState?: AccountNfts,
): Nft[] => {
// Return empty array if newState is missing (nothing new to compare)
if (!newState) return [];
// Treat undefined/null previousState as empty object (all NFTs will be considered new)
const prevState = previousState || {};
return getChainEntries(newState).flatMap(([chainId, newChainNfts]) => {
const previousChainNfts = prevState[chainId] || [];
return newChainNfts.filter(
(newNft) =>
!previousChainNfts.some((prevNft) => isMatchingNft(prevNft, newNft)),
);
});
};
export interface NftAnalyticsParams {
chain_id: number;
source: 'detected';
}
/**
* Compares previous and new NFT states and prepares analytics events for newly detected NFTs
* @param previousNfts - Previous state of NFTs grouped by chainId for a single account
* @param newNfts - New state of NFTs grouped by chainId for a single account
* @param paramBuilder - Function to build analytics parameters for each NFT
* @returns Array of analytics event params for newly detected NFTs
*/
export const prepareNftDetectionEvents = (
previousNfts: AccountNfts | undefined,
newNfts: AccountNfts | undefined,
paramBuilder: (nft: Nft) => NftAnalyticsParams | undefined,
) => {
const paramsToSend: NftAnalyticsParams[] = [];
if (!isEqual(previousNfts, newNfts)) {
const newlyDetectedNfts = compareNftStates(previousNfts, newNfts);
newlyDetectedNfts.forEach((nft) => {
const params = paramBuilder(nft);
if (params) {
paramsToSend.push(params);
}
});
}
return paramsToSend;
};