-
Notifications
You must be signed in to change notification settings - Fork 586
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add utility functions from upstream dependency (#563)
- Loading branch information
1 parent
1cb1ba0
commit 98dde95
Showing
7 changed files
with
253 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
import { TokenInfo } from "./types"; | ||
|
||
export type TokenInfoChangeKey = Exclude< | ||
keyof TokenInfo, | ||
"address" | "chainId" | ||
>; | ||
export type TokenInfoChanges = Array<TokenInfoChangeKey>; | ||
|
||
/** | ||
* compares two token info key values | ||
* this subset of full deep equal functionality does not work on objects or object arrays | ||
* @param a comparison item a | ||
* @param b comparison item b | ||
*/ | ||
function compareTokenInfoProperty(a: unknown, b: unknown): boolean { | ||
if (a === b) return true; | ||
if (typeof a !== typeof b) return false; | ||
if (Array.isArray(a) && Array.isArray(b)) { | ||
return a.every((el, i) => b[i] === el); | ||
} | ||
return false; | ||
} | ||
|
||
/** | ||
* Differences between a base list and an updated list. | ||
*/ | ||
export interface TokenListDiff { | ||
/** | ||
* Tokens from updated with chainId/address not present in base list | ||
*/ | ||
readonly added: TokenInfo[]; | ||
/** | ||
* Tokens from base with chainId/address not present in the updated list | ||
*/ | ||
readonly removed: TokenInfo[]; | ||
/** | ||
* The token info that changed | ||
*/ | ||
readonly changed: { | ||
[chainId: number]: { | ||
[address: string]: TokenInfoChanges; | ||
}; | ||
}; | ||
} | ||
|
||
/** | ||
* Computes the diff of a token list where the first argument is the base and the second argument is the updated list. | ||
* @param base base list | ||
* @param update updated list | ||
*/ | ||
export function diffTokenLists( | ||
base: TokenInfo[], | ||
update: TokenInfo[] | ||
): TokenListDiff { | ||
const indexedBase = base.reduce<{ | ||
[chainId: number]: { [address: string]: TokenInfo }; | ||
}>((memo, tokenInfo) => { | ||
if (!memo[tokenInfo.chainId]) memo[tokenInfo.chainId] = {}; | ||
memo[tokenInfo.chainId][tokenInfo.address] = tokenInfo; | ||
return memo; | ||
}, {}); | ||
|
||
const newListUpdates = update.reduce<{ | ||
added: TokenInfo[]; | ||
changed: { | ||
[chainId: number]: { | ||
[address: string]: TokenInfoChanges; | ||
}; | ||
}; | ||
index: { | ||
[chainId: number]: { | ||
[address: string]: true; | ||
}; | ||
}; | ||
}>( | ||
(memo, tokenInfo) => { | ||
const baseToken = indexedBase[tokenInfo.chainId]?.[tokenInfo.address]; | ||
if (!baseToken) { | ||
memo.added.push(tokenInfo); | ||
} else { | ||
const changes: TokenInfoChanges = Object.keys(tokenInfo) | ||
.filter( | ||
(s): s is TokenInfoChangeKey => s !== "address" && s !== "chainId" | ||
) | ||
.filter((s) => { | ||
return !compareTokenInfoProperty(tokenInfo[s], baseToken[s]); | ||
}); | ||
if (changes.length > 0) { | ||
if (!memo.changed[tokenInfo.chainId]) { | ||
memo.changed[tokenInfo.chainId] = {}; | ||
} | ||
memo.changed[tokenInfo.chainId][tokenInfo.address] = changes; | ||
} | ||
} | ||
|
||
if (!memo.index[tokenInfo.chainId]) { | ||
memo.index[tokenInfo.chainId] = { | ||
[tokenInfo.address]: true, | ||
}; | ||
} else { | ||
memo.index[tokenInfo.chainId][tokenInfo.address] = true; | ||
} | ||
|
||
return memo; | ||
}, | ||
{ added: [], changed: {}, index: {} } | ||
); | ||
|
||
const removed = base.reduce<TokenInfo[]>((list, curr) => { | ||
if ( | ||
!newListUpdates.index[curr.chainId] || | ||
!newListUpdates.index[curr.chainId][curr.address] | ||
) { | ||
list.push(curr); | ||
} | ||
return list; | ||
}, []); | ||
|
||
return { | ||
added: newListUpdates.added, | ||
changed: newListUpdates.changed, | ||
removed, | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import { Version } from "./types"; | ||
|
||
/** | ||
* Enum describing types of version differences | ||
*/ | ||
export enum VersionUpgrade { | ||
NONE, | ||
PATCH, | ||
MINOR, | ||
MAJOR, | ||
} | ||
|
||
/** | ||
* Return the upgrade type from the base version to the update version. | ||
* Note that downgrades and equivalent versions are both treated as `NONE`. | ||
* @param base base list | ||
* @param update update to the list | ||
*/ | ||
export function getVersionUpgrade( | ||
base: Version, | ||
update: Version | ||
): VersionUpgrade { | ||
if (update.major > base.major) { | ||
return VersionUpgrade.MAJOR; | ||
} | ||
if (update.major < base.major) { | ||
return VersionUpgrade.NONE; | ||
} | ||
if (update.minor > base.minor) { | ||
return VersionUpgrade.MINOR; | ||
} | ||
if (update.minor < base.minor) { | ||
return VersionUpgrade.NONE; | ||
} | ||
return update.patch > base.patch ? VersionUpgrade.PATCH : VersionUpgrade.NONE; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import { versionComparator } from './versionComparator'; | ||
import { Version } from './types'; | ||
|
||
/** | ||
* Returns true if versionB is an update over versionA | ||
*/ | ||
export function isVersionUpdate(base: Version, update: Version): boolean { | ||
return versionComparator(base, update) < 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { diffTokenLists } from "./diffTokenLists"; | ||
import { VersionUpgrade } from "./getVersionUpgrade"; | ||
import { TokenInfo } from "./types"; | ||
|
||
/** | ||
* Returns the minimum version bump for the given list | ||
* @param baseList the base list of tokens | ||
* @param updatedList the updated list of tokens | ||
*/ | ||
export function minVersionBump( | ||
baseList: TokenInfo[], | ||
updatedList: TokenInfo[] | ||
): VersionUpgrade { | ||
const diff = diffTokenLists(baseList, updatedList); | ||
if (diff.removed.length > 0) return VersionUpgrade.MAJOR; | ||
if (diff.added.length > 0) return VersionUpgrade.MINOR; | ||
if (Object.keys(diff.changed).length > 0) return VersionUpgrade.PATCH; | ||
return VersionUpgrade.NONE; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { VersionUpgrade } from "./getVersionUpgrade"; | ||
import { Version } from "./types"; | ||
|
||
/** | ||
* Returns the next version of the list given a base version and the upgrade type | ||
* @param base current version | ||
* @param bump the upgrade type | ||
*/ | ||
export function nextVersion(base: Version, bump: VersionUpgrade): Version { | ||
switch (bump) { | ||
case VersionUpgrade.NONE: | ||
return base; | ||
|
||
case VersionUpgrade.MAJOR: | ||
return { major: base.major + 1, minor: 0, patch: 0 }; | ||
|
||
case VersionUpgrade.MINOR: | ||
return { | ||
major: base.major, | ||
minor: base.minor + 1, | ||
patch: 0, | ||
}; | ||
|
||
case VersionUpgrade.PATCH: | ||
return { | ||
major: base.major, | ||
minor: base.minor, | ||
patch: base.patch + 1, | ||
}; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import { Version } from "./types"; | ||
|
||
/** | ||
* Comparator function that allows sorting version from lowest to highest | ||
* @param versionA version A to compare | ||
* @param versionB version B to compare | ||
* @returns -1 if versionA comes before versionB, 0 if versionA is equal to version B, and 1 if version A comes after version B | ||
*/ | ||
export function versionComparator( | ||
versionA: Version, | ||
versionB: Version | ||
): -1 | 0 | 1 { | ||
if (versionA.major < versionB.major) { | ||
return -1; | ||
} else if (versionA.major > versionB.major) { | ||
return 1; | ||
} else if (versionA.minor < versionB.minor) { | ||
return -1; | ||
} else if (versionA.minor > versionB.minor) { | ||
return 1; | ||
} else if (versionA.patch < versionB.patch) { | ||
return -1; | ||
} else if (versionA.patch > versionB.patch) { | ||
return 1; | ||
} else { | ||
return 0; | ||
} | ||
} |