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
|
"dev": true
|
||||||
},
|
},
|
||||||
"bignumber.js": {
|
"bignumber.js": {
|
||||||
"version": "7.2.1",
|
"version": "9.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-7.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.1.tgz",
|
||||||
"integrity": "sha512-S4XzBk5sMB+Rcb/LNcpzXr57VRTxgAvaAEDAl1AwRx27j00hT84O6OkteE7u8UB3NuaaygCRrEpqox4uDOrbdQ==",
|
"integrity": "sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"bindings": {
|
"bindings": {
|
||||||
|
@ -3630,6 +3630,12 @@
|
||||||
"integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=",
|
"integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=",
|
||||||
"dev": true
|
"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": {
|
"caseless": {
|
||||||
"version": "0.11.0",
|
"version": "0.11.0",
|
||||||
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz",
|
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz",
|
||||||
|
|
|
@ -10,7 +10,8 @@
|
||||||
"fix": "ts-node ./script/entrypoint/fix",
|
"fix": "ts-node ./script/entrypoint/fix",
|
||||||
"fix-sanity": "ts-node ./script/entrypoint/fix-sanity",
|
"fix-sanity": "ts-node ./script/entrypoint/fix-sanity",
|
||||||
"update": "ts-node ./script/entrypoint/update",
|
"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": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
@ -55,7 +56,8 @@
|
||||||
"tinify": "^1.6.0-beta.2",
|
"tinify": "^1.6.0-beta.2",
|
||||||
"ts-jest": "^25.5.1",
|
"ts-jest": "^25.5.1",
|
||||||
"ts-node": "^8.10.2",
|
"ts-node": "^8.10.2",
|
||||||
"typescript": "^3.9.7"
|
"typescript": "^3.9.7",
|
||||||
|
"bignumber.js": "^9.0.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"codecov": "^3.7.2"
|
"codecov": "^3.7.2"
|
||||||
|
|
|
@ -16,8 +16,6 @@ import {
|
||||||
} from "../generic/repo-structure";
|
} from "../generic/repo-structure";
|
||||||
|
|
||||||
const binanceChain = "binance";
|
const binanceChain = "binance";
|
||||||
const binanceUrlTokens2 = config.binanceUrlTokens2;
|
|
||||||
const binanceUrlTokens8 = config.binanceUrlTokens8;
|
|
||||||
const binanceUrlTokenAssets = config.binanceUrlTokenAssets;
|
const binanceUrlTokenAssets = config.binanceUrlTokenAssets;
|
||||||
let cachedAssets = [];
|
let cachedAssets = [];
|
||||||
|
|
||||||
|
@ -31,9 +29,9 @@ async function retrieveBep2AssetList(): Promise<unknown[]> {
|
||||||
async function retrieveAssets(): Promise<unknown[]> {
|
async function retrieveAssets(): Promise<unknown[]> {
|
||||||
// cache results because of rate limit, used more than once
|
// cache results because of rate limit, used more than once
|
||||||
if (cachedAssets.length == 0) {
|
if (cachedAssets.length == 0) {
|
||||||
console.log(` Retrieving token infos (${binanceUrlTokens2}, ${binanceUrlTokens8})`);
|
console.log(`Retrieving token infos`);
|
||||||
const bep2assets = await axios.get(binanceUrlTokens2);
|
const bep2assets = await axios.get(`${config.binanceDexURL}/v1/tokens?limit=1000`);
|
||||||
const bep8assets = await axios.get(binanceUrlTokens8);
|
const bep8assets = await axios.get(`${config.binanceDexURL}/v1/mini/tokens?limit=1000`);
|
||||||
cachedAssets = bep2assets.data.concat(bep8assets.data);
|
cachedAssets = bep2assets.data.concat(bep8assets.data);
|
||||||
}
|
}
|
||||||
console.log(`Using ${cachedAssets.length} assets`);
|
console.log(`Using ${cachedAssets.length} assets`);
|
||||||
|
|
|
@ -4,6 +4,6 @@ export const imageMinLogoWidth = 64;
|
||||||
export const imageMinLogoHeight = 64;
|
export const imageMinLogoHeight = 64;
|
||||||
export const imageMaxLogoSizeKb = 100;
|
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 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 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 {
|
import {
|
||||||
getChainAssetsList,
|
getChainAssetsList,
|
||||||
getChainAllowlistPath,
|
getChainAllowlistPath,
|
||||||
getChainDenylistPath
|
getChainDenylistPath
|
||||||
} from "../generic/repo-structure";
|
} from "./repo-structure";
|
||||||
import { readFileSync, writeFileSync } from "../generic/filesystem";
|
import { readFileSync, writeFileSync } from "./filesystem";
|
||||||
import {
|
import {
|
||||||
arrayDiff,
|
arrayDiff,
|
||||||
arrayDiffNocase,
|
arrayDiffNocase,
|
||||||
findCommonElementsOrDuplicates,
|
findCommonElementsOrDuplicates,
|
||||||
makeUnique
|
makeUnique
|
||||||
} from "../generic/types";
|
} from "./types";
|
||||||
import { ActionInterface, CheckStepInterface } from "../generic/interface";
|
import { ActionInterface, CheckStepInterface } from "./interface";
|
||||||
import { formatSortJson } from "../generic/json";
|
import { formatSortJson } from "./json";
|
||||||
import * as bluebird from "bluebird";
|
import * as bluebird from "bluebird";
|
||||||
|
|
||||||
async function checkUpdateAllowDenyList(chain: string, checkOnly: boolean ): Promise<[boolean, string[], string[]]> {
|
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];
|
return [(errorMsgs.length == 0 && warningMsgs.length == 0), errorMsgs, warningMsgs];
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Allowlist implements ActionInterface {
|
export class Allowlists implements ActionInterface {
|
||||||
getName(): string { return "Allowlists"; }
|
getName(): string { return "Allowlists"; }
|
||||||
|
|
||||||
getSanityChecks = null;
|
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 { TronAction } from "../blockchain/tron";
|
||||||
import { Validators } from "../generic/validators";
|
import { Validators } from "../generic/validators";
|
||||||
import { WavesAction } from "../blockchain/waves";
|
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 { ActionInterface, CheckStepInterface } from "../generic/interface";
|
||||||
import * as chalk from 'chalk';
|
import * as chalk from 'chalk';
|
||||||
import * as bluebird from "bluebird";
|
import * as bluebird from "bluebird";
|
||||||
|
@ -19,7 +20,8 @@ const actionList: ActionInterface[] = [
|
||||||
new FoldersFiles(),
|
new FoldersFiles(),
|
||||||
new EthForks(),
|
new EthForks(),
|
||||||
new LogoSize(),
|
new LogoSize(),
|
||||||
new Allowlist(),
|
new Allowlists(),
|
||||||
|
new TokenLists(),
|
||||||
new Validators(),
|
new Validators(),
|
||||||
new JsonAction(),
|
new JsonAction(),
|
||||||
// chains:
|
// 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