trustwallet-assets/script/blockchain/ethereum.ts
Adam R 88f26b09d1
[Internal] Retrieve trading pairs from PancakeSwap (#5355)
* Retrieve trading pairs from PancakeSwap.

* Retrieve trading pairs from Uniswap.

* Add doc link

* Lint fix

* Include decimals

* Move binance tokenlist generation to BinanceAction.

* Generate smartChain tokenlist, from base and pancakeswap pairs.

* Fix array types in tokenlists.ts

* Common writeToFile method, sort.

* Type fixes

* Revert tokenlist.json to master

* Include pairs with allowlisted coins only.

* Move assetID functions to common asset.ts

* Use common assetID functions.

* Use dynamic generation time.

* Keep constant generation time; Version in tokenlist.

* Count additions

* Update tokenlist version and timestamp if needed before save.

* No counting is needed in addXxxIfNeeded() functions.

* Tokenlist timestamp: take over if previous

* Update ethereum tokenlist with pairs from Uniswap.

* Increase query limit to 400 pairs.

* iDecimals always number, add decimal fields to Eth also.

* Include only pairs with primary tokens, add pair info to primary token only.

* Update base tokenlist (BSC) to current full list, in order not to remove any coins.

* Update base tokenlist (ETH) to current full list, in order not to remove any coins.

* Move out pair checks into common code.

* Add checks for volume and txCount.

* Assets tokenlist: Adjust token names for added tokens.

* Move parameters to central config.ts

* Nicer query string, compact

* Prevent change if subgraph API fails

* Reduce max limit in Pancakeswap query, with 400 often times out.

* Stricter error handling

* Reduce code duplication.

* Minor comment

* Display number of original tokens

* Lint fix

Co-authored-by: Catenocrypt <catenocrypt@users.noreply.github.com>
2021-01-29 07:45:43 +01:00

91 lines
3.3 KiB
TypeScript

import { ActionInterface, CheckStepInterface } from "../generic/interface";
import {
checkTradingPair,
getTradingPairs,
PairInfo,
primaryTokenIndex,
TokenInfo
} from "../generic/subgraph";
import { getChainAllowlistPath } from "../generic/repo-structure";
import { Ethereum } from "../generic/blockchains";
import { readJsonFile } from "../generic/json";
import {
rebuildTokenlist,
TokenItem
} from "../generic/tokenlists";
import { toChecksum } from "../generic/eth-address";
import { assetID, logoURI } from "../generic/asset";
import * as config from "../config"
const PrimaryTokens: string[] = ["WETH", "ETH"];
// Retrieve trading pairs from Uniswap
async function retrieveUniswapPairs(): Promise<PairInfo[]> {
console.log(`Retrieving pairs from Uniswap, limit liquidity USD ${config.Uniswap_MinLiquidity} volume ${config.Uniswap_MinVol24} txcount ${config.Uniswap_MinTxCount24}`);
// prepare phase, read allowlist
const allowlist: string[] = readJsonFile(getChainAllowlistPath(Ethereum)) as string[];
const pairs = await getTradingPairs(config.Uniswap_TradingPairsUrl, config.Uniswap_TradingPairsQuery);
const filtered: PairInfo[] = [];
pairs.forEach(x => {
try {
if (typeof(x) === "object") {
const pairInfo = x as PairInfo;
if (pairInfo) {
if (checkTradingPair(pairInfo, Ethereum, config.Uniswap_MinLiquidity, config.Uniswap_MinVol24, config.Uniswap_MinTxCount24, allowlist, PrimaryTokens)) {
filtered.push(pairInfo);
}
}
}
} catch (err) {
console.log("Exception:", err);
}
});
console.log("Retrieved & filtered", filtered.length, "pairs:");
filtered.forEach(p => {
console.log(`pair: ${p.token0.symbol} -- ${p.token1.symbol} \t USD ${Math.round(p.reserveUSD)} ${Math.round(p.volumeUSD)} ${p.txCount}`);
});
return filtered;
}
function tokenInfoFromSubgraphToken(token: TokenInfo): TokenItem {
const idChecksum = toChecksum(token.id);
return new TokenItem(
assetID(60, idChecksum),
"ERC20",
idChecksum, token.name, token.symbol, parseInt(token.decimals.toString()),
logoURI(idChecksum, "ethereum", "--"),
[]);
}
// Retrieve trading pairs from PancakeSwap
async function generateTokenlist(): Promise<void> {
// note: if [] is returned here for some reason, all pairs will be *removed*. In case of error (e.g. timeout) it should throw
const tradingPairs = await retrieveUniswapPairs();
// convert
const pairs2: [TokenItem, TokenItem][] = [];
tradingPairs.forEach(p => {
let tokenItem0 = tokenInfoFromSubgraphToken(p.token0);
let tokenItem1 = tokenInfoFromSubgraphToken(p.token1);
if (primaryTokenIndex(p, PrimaryTokens) == 2) {
// reverse
const tmp = tokenItem1; tokenItem1 = tokenItem0; tokenItem0 = tmp;
}
pairs2.push([tokenItem0, tokenItem1]);
});
await rebuildTokenlist(Ethereum, pairs2, "Ethereum");
}
export class EthereumAction implements ActionInterface {
getName(): string { return "Ethereum"; }
getSanityChecks(): CheckStepInterface[] { return []; }
async update(): Promise<void> {
await generateTokenlist();
}
}