mirror of
https://github.com/Instadapp/trustwallet-assets.git
synced 2024-07-29 22:37:31 +00:00
Add token list support for pairs on binance chain (#4428)
* Add token list support for pairs on binance chain * Update tokenlists.ts * Update tokenlists.ts * Update tokenlists.ts * Fix asset for bnb pair * Update package-lock.json * Add models for token list * Add BinanceMarket
This commit is contained in:
parent
62a6265eed
commit
9b41a52182
File diff suppressed because it is too large
Load Diff
12
package-lock.json
generated
12
package-lock.json
generated
|
@ -1930,9 +1930,9 @@
|
|||
"dev": true
|
||||
},
|
||||
"bignumber.js": {
|
||||
"version": "7.2.1",
|
||||
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-7.2.1.tgz",
|
||||
"integrity": "sha512-S4XzBk5sMB+Rcb/LNcpzXr57VRTxgAvaAEDAl1AwRx27j00hT84O6OkteE7u8UB3NuaaygCRrEpqox4uDOrbdQ==",
|
||||
"version": "9.0.1",
|
||||
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.1.tgz",
|
||||
"integrity": "sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA==",
|
||||
"dev": true
|
||||
},
|
||||
"bindings": {
|
||||
|
@ -3630,6 +3630,12 @@
|
|||
"integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=",
|
||||
"dev": true
|
||||
},
|
||||
"bignumber.js": {
|
||||
"version": "7.2.1",
|
||||
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-7.2.1.tgz",
|
||||
"integrity": "sha512-S4XzBk5sMB+Rcb/LNcpzXr57VRTxgAvaAEDAl1AwRx27j00hT84O6OkteE7u8UB3NuaaygCRrEpqox4uDOrbdQ==",
|
||||
"dev": true
|
||||
},
|
||||
"caseless": {
|
||||
"version": "0.11.0",
|
||||
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz",
|
||||
|
|
|
@ -10,7 +10,8 @@
|
|||
"fix": "ts-node ./script/entrypoint/fix",
|
||||
"fix-sanity": "ts-node ./script/entrypoint/fix-sanity",
|
||||
"update": "ts-node ./script/entrypoint/update",
|
||||
"lint": "npx eslint . --ext .js,.jsx,.ts,.tsx"
|
||||
"lint": "npx eslint . --ext .js,.jsx,.ts,.tsx",
|
||||
"lint:fix": "npx eslint . --ext .js,.jsx,.ts,.tsx --fix"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -55,7 +56,8 @@
|
|||
"tinify": "^1.6.0-beta.2",
|
||||
"ts-jest": "^25.5.1",
|
||||
"ts-node": "^8.10.2",
|
||||
"typescript": "^3.9.7"
|
||||
"typescript": "^3.9.7",
|
||||
"bignumber.js": "^9.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"codecov": "^3.7.2"
|
||||
|
|
|
@ -16,27 +16,25 @@ import {
|
|||
} from "../generic/repo-structure";
|
||||
|
||||
const binanceChain = "binance";
|
||||
const binanceUrlTokens2 = config.binanceUrlTokens2;
|
||||
const binanceUrlTokens8 = config.binanceUrlTokens8;
|
||||
const binanceUrlTokenAssets = config.binanceUrlTokenAssets;
|
||||
let cachedAssets = [];
|
||||
|
||||
async function retrieveBep2AssetList(): Promise<unknown[]> {
|
||||
console.log(` Retrieving token asset infos from: ${binanceUrlTokenAssets}`);
|
||||
console.log(`Retrieving token asset infos from: ${binanceUrlTokenAssets}`);
|
||||
const { assetInfoList } = await axios.get(binanceUrlTokenAssets).then(r => r.data);
|
||||
console.log(` Retrieved ${assetInfoList.length} token asset infos`);
|
||||
console.log(`Retrieved ${assetInfoList.length} token asset infos`);
|
||||
return assetInfoList
|
||||
}
|
||||
|
||||
async function retrieveAssets(): Promise<unknown[]> {
|
||||
// cache results because of rate limit, used more than once
|
||||
if (cachedAssets.length == 0) {
|
||||
console.log(` Retrieving token infos (${binanceUrlTokens2}, ${binanceUrlTokens8})`);
|
||||
const bep2assets = await axios.get(binanceUrlTokens2);
|
||||
const bep8assets = await axios.get(binanceUrlTokens8);
|
||||
console.log(`Retrieving token infos`);
|
||||
const bep2assets = await axios.get(`${config.binanceDexURL}/v1/tokens?limit=1000`);
|
||||
const bep8assets = await axios.get(`${config.binanceDexURL}/v1/mini/tokens?limit=1000`);
|
||||
cachedAssets = bep2assets.data.concat(bep8assets.data);
|
||||
}
|
||||
console.log(` Using ${cachedAssets.length} assets`);
|
||||
console.log(`Using ${cachedAssets.length} assets`);
|
||||
return cachedAssets;
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,6 @@ export const imageMinLogoWidth = 64;
|
|||
export const imageMinLogoHeight = 64;
|
||||
export const imageMaxLogoSizeKb = 100;
|
||||
export const foldersRootdirAllowedFiles: string[] = [".github", "blockchains", "dapps", "media", "node_modules", "script-old", "script", "test", ".gitignore", "azure-pipelines.yml", "jest.config.js", "LICENSE", "package-lock.json", "package.json", "README.md", ".git", "dangerfile.ts", "Gemfile", "Gemfile.lock", ".eslintignore", ".eslintrc.js"];
|
||||
export const binanceUrlTokens2 = "https://dex-atlantic.binance.org/api/v1/tokens?limit=1000";
|
||||
export const binanceUrlTokens8 = "https://dex-atlantic.binance.org/api/v1/mini/tokens?limit=1000";
|
||||
export const binanceUrlTokenAssets = "https://explorer.binance.org/api/v1/assets?page=1&rows=1000";
|
||||
export const binanceDexURL = 'https://dex-atlantic.binance.org/api'
|
||||
export const assetsURL = 'https://raw.githubusercontent.com/trustwallet/assets/master'
|
|
@ -1,18 +1,18 @@
|
|||
import { chainsWithDenylist } from "../generic/blockchains";
|
||||
import { chainsWithDenylist } from "./blockchains";
|
||||
import {
|
||||
getChainAssetsList,
|
||||
getChainAllowlistPath,
|
||||
getChainDenylistPath
|
||||
} from "../generic/repo-structure";
|
||||
import { readFileSync, writeFileSync } from "../generic/filesystem";
|
||||
} from "./repo-structure";
|
||||
import { readFileSync, writeFileSync } from "./filesystem";
|
||||
import {
|
||||
arrayDiff,
|
||||
arrayDiffNocase,
|
||||
findCommonElementsOrDuplicates,
|
||||
makeUnique
|
||||
} from "../generic/types";
|
||||
import { ActionInterface, CheckStepInterface } from "../generic/interface";
|
||||
import { formatSortJson } from "../generic/json";
|
||||
} from "./types";
|
||||
import { ActionInterface, CheckStepInterface } from "./interface";
|
||||
import { formatSortJson } from "./json";
|
||||
import * as bluebird from "bluebird";
|
||||
|
||||
async function checkUpdateAllowDenyList(chain: string, checkOnly: boolean ): Promise<[boolean, string[], string[]]> {
|
||||
|
@ -85,7 +85,7 @@ async function checkUpdateAllowDenyList(chain: string, checkOnly: boolean ): Pro
|
|||
return [(errorMsgs.length == 0 && warningMsgs.length == 0), errorMsgs, warningMsgs];
|
||||
}
|
||||
|
||||
export class Allowlist implements ActionInterface {
|
||||
export class Allowlists implements ActionInterface {
|
||||
getName(): string { return "Allowlists"; }
|
||||
|
||||
getSanityChecks = null;
|
||||
|
|
6
script/generic/asset.ts
Normal file
6
script/generic/asset.ts
Normal file
|
@ -0,0 +1,6 @@
|
|||
export function assetID(coin: number, token_id = ``): string {
|
||||
if (token_id.length > 0) {
|
||||
return `c${coin}_t${token_id}`
|
||||
}
|
||||
return `c${coin}`
|
||||
}
|
9
script/generic/numbers.ts
Normal file
9
script/generic/numbers.ts
Normal file
|
@ -0,0 +1,9 @@
|
|||
import BigNumber from "bignumber.js";
|
||||
|
||||
export function toSatoshis(value: string, decimals: number): string {
|
||||
return new BigNumber(value).multipliedBy(new BigNumber(10).exponentiatedBy(decimals)).toFixed()
|
||||
}
|
||||
|
||||
export function fromSatoshis(value: string, decimals: number): string {
|
||||
return new BigNumber(value).dividedBy(new BigNumber(10).exponentiatedBy(decimals)).toFixed()
|
||||
}
|
170
script/generic/tokenlists.ts
Normal file
170
script/generic/tokenlists.ts
Normal file
|
@ -0,0 +1,170 @@
|
|||
import { ActionInterface, CheckStepInterface } from "./interface";
|
||||
import axios from "axios";
|
||||
import {
|
||||
getChainTokenlistPath
|
||||
} from "./repo-structure";
|
||||
import { Binance } from "./blockchains";
|
||||
import { writeFileSync } from "./filesystem";
|
||||
import { formatJson } from "./json";
|
||||
import { assetID } from "./asset";
|
||||
import * as config from "../config";
|
||||
import { CoinType } from "@trustwallet/wallet-core";
|
||||
import { toSatoshis } from "./numbers";
|
||||
|
||||
class BinanceMarket {
|
||||
base_asset_symbol: string
|
||||
quote_asset_symbol: string
|
||||
lot_size: string
|
||||
tick_size: string
|
||||
}
|
||||
|
||||
class Version {
|
||||
major: number
|
||||
minor: number
|
||||
patch: number
|
||||
|
||||
constructor(major: number, minor: number, patch: number) {
|
||||
this.major = major
|
||||
this.minor = minor
|
||||
this.patch = patch
|
||||
}
|
||||
}
|
||||
|
||||
class List {
|
||||
name: string
|
||||
logoURI: string
|
||||
timestamp: string
|
||||
tokens: [TokenItem]
|
||||
pairs: [Pair]
|
||||
version: Version
|
||||
|
||||
constructor(name: string, logoURI: string, timestamp: string, tokens: [TokenItem], version: Version) {
|
||||
this.name = name
|
||||
this.logoURI = logoURI
|
||||
this.timestamp = timestamp;
|
||||
this.tokens = tokens
|
||||
this.version = version
|
||||
}
|
||||
}
|
||||
|
||||
class TokenItem {
|
||||
asset: string;
|
||||
address: string;
|
||||
name: string;
|
||||
symbol: string;
|
||||
decimals: number;
|
||||
logoURI: string;
|
||||
pairs: [Pair];
|
||||
|
||||
constructor(asset: string, address: string, name: string, symbol: string, decimals: number, logoURI: string, pairs: [Pair]) {
|
||||
this.asset = asset
|
||||
this.address = address
|
||||
this.name = name;
|
||||
this.symbol = symbol
|
||||
this.decimals = decimals
|
||||
this.logoURI = logoURI
|
||||
this.pairs = pairs
|
||||
}
|
||||
}
|
||||
|
||||
class Pair {
|
||||
base: string;
|
||||
lotSize: string;
|
||||
tickSize: string;
|
||||
|
||||
constructor(base: string, lotSize: string, tickSize: string) {
|
||||
this.base = base
|
||||
this.lotSize = lotSize
|
||||
this.tickSize = tickSize
|
||||
}
|
||||
}
|
||||
|
||||
export class TokenLists implements ActionInterface {
|
||||
getName(): string { return "TokenLists"; }
|
||||
|
||||
getSanityChecks = null;
|
||||
|
||||
getConsistencyChecks(): CheckStepInterface[] {
|
||||
const steps: CheckStepInterface[] = [];
|
||||
return steps;
|
||||
}
|
||||
|
||||
async consistencyFix(): Promise<void> {
|
||||
|
||||
// binance chain list
|
||||
const list = await generateBinanceTokensList()
|
||||
writeFileSync(getChainTokenlistPath(Binance), formatJson(generateTokensList(list)));
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
function generateTokensList(tokens: [TokenItem]): List {
|
||||
return new List(
|
||||
"Trust Wallet: BNB",
|
||||
"https://trustwallet.com/assets/images/favicon.png",
|
||||
"2020-10-03T12:37:57.000+00:00",
|
||||
tokens,
|
||||
new Version(0, 1, 0)
|
||||
)
|
||||
}
|
||||
|
||||
async function generateBinanceTokensList(): Promise<[TokenItem]> {
|
||||
const decimals = CoinType.decimals(CoinType.binance)
|
||||
const BNBSymbol = CoinType.symbol(CoinType.binance)
|
||||
const markets: [BinanceMarket] = await axios.get(`${config.binanceDexURL}/v1/markets?limit=10000`).then(r => r.data);
|
||||
const tokens = await axios.get(`${config.binanceDexURL}/v1/tokens?limit=10000`).then(r => r.data);
|
||||
const tokensMap = Object.assign({}, ...tokens.map(s => ({[s.symbol]: s})));
|
||||
const pairsMap = {}
|
||||
const pairsList = new Set();
|
||||
|
||||
markets.forEach(market => {
|
||||
const key = market.quote_asset_symbol
|
||||
|
||||
function pair(market: BinanceMarket): Pair {
|
||||
return new Pair(
|
||||
asset(market.base_asset_symbol),
|
||||
toSatoshis(market.lot_size, decimals),
|
||||
toSatoshis(market.tick_size, decimals)
|
||||
)
|
||||
}
|
||||
|
||||
if (pairsMap[key]) {
|
||||
const newList = pairsMap[key]
|
||||
newList.push(pair(market))
|
||||
pairsMap[key] = newList
|
||||
} else {
|
||||
pairsMap[key] = [
|
||||
pair(market)
|
||||
]
|
||||
}
|
||||
pairsList.add(market.base_asset_symbol)
|
||||
pairsList.add(market.quote_asset_symbol)
|
||||
})
|
||||
|
||||
function logoURI(symbol: string): string {
|
||||
if (symbol == BNBSymbol) {
|
||||
return `${config.assetsURL}/blockchains/binance/assets/${symbol}/logo.png`
|
||||
}
|
||||
return `${config.assetsURL}/blockchains/binance/assets/${symbol}/logo.png`
|
||||
}
|
||||
function asset(symbol: string): string {
|
||||
if (symbol == BNBSymbol) {
|
||||
return assetID(CoinType.binance)
|
||||
}
|
||||
return assetID(CoinType.binance, symbol)
|
||||
}
|
||||
const list = <[TokenItem]>Array.from(pairsList.values())
|
||||
return <[TokenItem]>list.map(item => {
|
||||
const token = tokensMap[item.symbol]
|
||||
return new TokenItem (
|
||||
asset(token.symbol),
|
||||
token.symbol,
|
||||
token.name,
|
||||
token.symbol,
|
||||
decimals,
|
||||
logoURI(token.symbol),
|
||||
pairsMap[token.symbol] || []
|
||||
)
|
||||
}).sort((n1,n2) => (n2.pairs || []).length - (n1.pairs || []).length);
|
||||
}
|
|
@ -10,7 +10,8 @@ import { TezosAction } from "../blockchain/tezos";
|
|||
import { TronAction } from "../blockchain/tron";
|
||||
import { Validators } from "../generic/validators";
|
||||
import { WavesAction } from "../blockchain/waves";
|
||||
import { Allowlist } from "../generic/allowlists";
|
||||
import { Allowlists } from "../generic/allowlists";
|
||||
import { TokenLists } from "../generic/tokenlists";
|
||||
import { ActionInterface, CheckStepInterface } from "../generic/interface";
|
||||
import * as chalk from 'chalk';
|
||||
import * as bluebird from "bluebird";
|
||||
|
@ -19,7 +20,8 @@ const actionList: ActionInterface[] = [
|
|||
new FoldersFiles(),
|
||||
new EthForks(),
|
||||
new LogoSize(),
|
||||
new Allowlist(),
|
||||
new Allowlists(),
|
||||
new TokenLists(),
|
||||
new Validators(),
|
||||
new JsonAction(),
|
||||
// chains:
|
||||
|
|
13
test/asset.test.ts
Normal file
13
test/asset.test.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
import {
|
||||
assetID
|
||||
} from "../script/generic/asset";
|
||||
|
||||
describe("Test eth-address helpers", () => {
|
||||
test(`Test coin`, () => {
|
||||
expect(assetID(714)).toEqual('c714');
|
||||
expect(assetID(714, '')).toEqual('c714');
|
||||
});
|
||||
test(`Test token`, () => {
|
||||
expect(assetID(714, 'TWT-8C2')).toEqual('c714_tTWT-8C2');
|
||||
});
|
||||
});
|
18
test/numbers.test.ts
Normal file
18
test/numbers.test.ts
Normal file
|
@ -0,0 +1,18 @@
|
|||
import {
|
||||
toSatoshis,
|
||||
fromSatoshis
|
||||
} from "../script/generic/numbers";
|
||||
|
||||
describe("Test eth-address helpers", () => {
|
||||
test(`Test to satoshis`, () => {
|
||||
expect(toSatoshis('43523.423423432112321234', 18)).toEqual('43523423423432112321234');
|
||||
expect(toSatoshis('0.123', 3)).toEqual('123');
|
||||
expect(toSatoshis('0.00000001', 8)).toEqual('1');
|
||||
});
|
||||
test(`Test from Satoshis`, () => {
|
||||
expect(fromSatoshis('123', 3)).toEqual('0.123');
|
||||
expect(fromSatoshis('1234', 3)).toEqual('1.234');
|
||||
expect(fromSatoshis('43523423423432112321234', 18)).toEqual('43523.423423432112321234');
|
||||
expect(fromSatoshis('1', 8)).toEqual('0.00000001');
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user