Add tokenlist validation (#17111)

* Add tokenlist validation

* Fix according to review
This commit is contained in:
Daniel 2022-01-07 14:45:16 +03:00 committed by GitHub
parent 905931934d
commit e7f9efcd2c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 126 additions and 138 deletions

View File

@ -37,6 +37,7 @@ validators_settings:
- "go.sum"
- ".golangci.yml"
- "Makefile"
- "bin"
skip_files:
- "node_modules"

View File

@ -1,7 +1,7 @@
{
"name": "BakeryToken",
"type": "BEP2",
"symbol": "BAKE-5E0",
"symbol": "BAKE",
"decimals": 8,
"website": "",
"description": "-",

View File

@ -1,7 +1,7 @@
{
"name": "Burger Swap",
"type": "BEP2",
"symbol": "BURGER-33A",
"symbol": "BURGER",
"decimals": 8,
"website": "",
"description": "-",

View File

@ -1089,16 +1089,6 @@
"logoURI": "https://assets.trustwalletapp.com/blockchains/binance/assets/BET-844/logo.png",
"pairs": []
},
{
"asset": "c714_tBIFI-290",
"type": "BEP2",
"address": "BIFI-290",
"name": "beefy.finance",
"symbol": "BIFI",
"decimals": 8,
"logoURI": "https://assets.trustwalletapp.com/blockchains/binance/assets/BIFI-290/logo.png",
"pairs": []
},
{
"asset": "c714_tBKBT-3A6",
"type": "BEP2",

View File

@ -1,6 +1,6 @@
{
"name": "LTO",
"symbol": "XLTO",
"symbol": "LTO",
"type": "ERC20",
"decimals": 8,
"description": "Old ERC20 Smart Contract for LTO Network, please swap to v2. LTO Network is a layer-1 platform for decentralized identities, verifiable credentials and decentralized workflow applications, while maintaining data privacy and GDPR compliance.",

View File

@ -1,7 +1,7 @@
{
"name": "Wrapped CrescoFin (WCRES)",
"type": "ERC20",
"symbol": "WCRES",
"symbol": "wCRES",
"decimals": 18,
"website": "https://defi.crescofin.ch",
"description": "wCRES represents unregistered equity in CrescoFin, a better banking alternative, with higher rates than in a bank and fully insured deposits and returns.\n\nIncorporated and regulated in Switzerland.",

View File

@ -1350,7 +1350,7 @@
{
"asset": "c60_t0x41a3dba3d677e573636ba691a70ff2d606c29666",
"type": "ERC20",
"address": "0x41a3dba3d677e573636ba691a70ff2d606c29666",
"address": "0x41A3Dba3D677E573636BA691a70ff2D606c29666",
"name": "GoBlank",
"symbol": "BLANK",
"decimals": 18,
@ -1503,7 +1503,7 @@
"type": "ERC20",
"address": "0x514910771AF9Ca656af840dff83E8264EcF986CA",
"name": "ChainLink",
"symbol": "Link",
"symbol": "LINK",
"decimals": 18,
"logoURI": "https://assets.trustwalletapp.com/blockchains/ethereum/assets/0x514910771AF9Ca656af840dff83E8264EcF986CA/logo.png",
"pairs": []
@ -2190,16 +2190,6 @@
"logoURI": "https://assets.trustwalletapp.com/blockchains/ethereum/assets/0x8c15Ef5b4B21951d50E53E4fbdA8298FFAD25057/logo.png",
"pairs": []
},
{
"asset": "c60_t0x8c8687fC965593DFb2F0b4EAeFD55E9D8df348df",
"type": "ERC20",
"address": "0x8c8687fC965593DFb2F0b4EAeFD55E9D8df348df",
"name": "PAID Network",
"symbol": "PAID",
"decimals": 18,
"logoURI": "https://assets.trustwalletapp.com/blockchains/ethereum/assets/0x8c8687fC965593DFb2F0b4EAeFD55E9D8df348df/logo.png",
"pairs": []
},
{
"chainId": 1,
"asset": "c60_t0x8CE9137d39326AD0cD6491fb5CC0CbA0e089b6A9",
@ -3178,7 +3168,7 @@
"type": "ERC20",
"address": "0xdd974D5C2e2928deA5F71b9825b8b646686BD200",
"name": "Kyber Network Crystal",
"symbol": "KNC",
"symbol": "KNCL",
"decimals": 18,
"logoURI": "https://assets.trustwalletapp.com/blockchains/ethereum/assets/0xdd974D5C2e2928deA5F71b9825b8b646686BD200/logo.png",
"pairs": []
@ -3279,7 +3269,7 @@
"type": "ERC20",
"address": "0xE95A203B1a91a908F9B9CE46459d101078c2c3cb",
"name": "aEthereum",
"symbol": "aEth",
"symbol": "aETHc",
"decimals": 18,
"logoURI": "https://assets.trustwalletapp.com/blockchains/ethereum/assets/0xE95A203B1a91a908F9B9CE46459d101078c2c3cb/logo.png",
"pairs": []

View File

@ -1,5 +1,5 @@
{
"name": "Filecoin",
"name": "Binance-Peg Filecoin",
"website": "https://filecoin.io",
"description": "Filecoin provides a blockchain-based marketplace that aims to revolutionize the global storage economy.",
"explorer": "https://bscscan.com/token/0x0D8Ce2A99Bb6e3B7Db580eD848240e4a0F9aE153",

View File

@ -5,7 +5,7 @@
"explorer": "https://bscscan.com/token/0x63870a18b6e42b01ef1ad8a2302ef50b7132054f",
"research": "",
"type": "BEP20",
"symbol": "blink",
"symbol": "BLINK",
"decimals": 6,
"status": "active",
"id": "0x63870A18B6e42b01Ef1Ad8A2302ef50B7132054F"

View File

@ -213,7 +213,7 @@
"type": "BEP20",
"address": "0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82",
"name": "PancakeSwap Token",
"symbol": "Cake",
"symbol": "CAKE",
"decimals": 18,
"logoURI": "https://assets.trustwalletapp.com/blockchains/smartchain/assets/0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82/logo.png",
"pairs": []
@ -511,7 +511,7 @@
"address": "0x78650B139471520656b9E7aA7A5e9276814a38e9",
"name": "StandardBTCHashrateToken",
"symbol": "BTCST",
"decimals": 18,
"decimals": 17,
"logoURI": "https://assets.trustwalletapp.com/blockchains/smartchain/assets/0x78650B139471520656b9E7aA7A5e9276814a38e9/logo.png",
"pairs": []
},

16
go.sum
View File

@ -40,26 +40,10 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/trustwallet/assets-go-libs v0.0.16 h1:nbKrf/pHKQCut4Q5Mdg5BinLdFxOqvzEeAgIgzX0/P8=
github.com/trustwallet/assets-go-libs v0.0.16/go.mod h1:agKWTQ9ECSzQ++7P/9viSxJnG1Kp+WhfDyI3pAmtnVM=
github.com/trustwallet/assets-go-libs v0.0.17-0.20211220141041-3b3a722649fa h1:d+FAYtxmN8mJK9jobkzOotwSEU2KPZ9H4gmuBg6dv3M=
github.com/trustwallet/assets-go-libs v0.0.17-0.20211220141041-3b3a722649fa/go.mod h1:agKWTQ9ECSzQ++7P/9viSxJnG1Kp+WhfDyI3pAmtnVM=
github.com/trustwallet/assets-go-libs v0.0.17-0.20211220141745-408afc4f7467 h1:JYCmTXnQfR/RElBY9aFppwLVwvy7wuBNbtW5f31j1Vs=
github.com/trustwallet/assets-go-libs v0.0.17-0.20211220141745-408afc4f7467/go.mod h1:agKWTQ9ECSzQ++7P/9viSxJnG1Kp+WhfDyI3pAmtnVM=
github.com/trustwallet/assets-go-libs v0.0.17-0.20211220144503-44a66d3a5e92 h1:TT3IFY3cBZBQAMdoVA8bzdH8q58d8hkiiVpBAmZJ+J8=
github.com/trustwallet/assets-go-libs v0.0.17-0.20211220144503-44a66d3a5e92/go.mod h1:agKWTQ9ECSzQ++7P/9viSxJnG1Kp+WhfDyI3pAmtnVM=
github.com/trustwallet/assets-go-libs v0.0.17 h1:s/XF4C7peyFuKadoRr9YhjfMoWAx9yKzk2IFmtT5ZpM=
github.com/trustwallet/assets-go-libs v0.0.17/go.mod h1:agKWTQ9ECSzQ++7P/9viSxJnG1Kp+WhfDyI3pAmtnVM=
github.com/trustwallet/assets-go-libs v0.0.19-0.20211224113937-74dc923bd4b5 h1:3bqdCY+jcpx6QCYc+Eb/Kci3ZRljI7CP6t3H+JhKAmo=
github.com/trustwallet/assets-go-libs v0.0.19-0.20211224113937-74dc923bd4b5/go.mod h1:jPJ2JP6SF+/6fXLETojEtSssCB5Lyeid8rjS6NLS4e4=
github.com/trustwallet/assets-go-libs v0.0.19-0.20211224115115-e2089570f2fd h1:QtDE54pHNtql9sQvyAyO6alzyaXcnIUuwNytcF25EyU=
github.com/trustwallet/assets-go-libs v0.0.19-0.20211224115115-e2089570f2fd/go.mod h1:jPJ2JP6SF+/6fXLETojEtSssCB5Lyeid8rjS6NLS4e4=
github.com/trustwallet/assets-go-libs v0.0.19 h1:Zn7su7wSrJLOHSeEoM+jz8smmIFsX+tAGI3FQ7rwwqQ=
github.com/trustwallet/assets-go-libs v0.0.19/go.mod h1:/il5tQtqP3uSDbyDTfP1OsL3kSIg+v6+QBRz3okXZpc=
github.com/trustwallet/go-libs v0.2.21-0.20211217144209-59d4828f9793 h1:KFtyLpBPbMyUdeCth/Zcej/SSgAFIo6fxdS2eEPEg3I=
github.com/trustwallet/go-libs v0.2.21-0.20211217144209-59d4828f9793/go.mod h1:7QdAp1lcteKKI0DYqGoaO8KO4eTNYjGmg8vHy0YXkKc=
github.com/trustwallet/go-primitives v0.0.17 h1:1fBxZMKGCHdHtgdUzsqdFlD21+1GneIk/sxN6jxYBds=
github.com/trustwallet/go-primitives v0.0.17/go.mod h1:jLqd7rm+4EYG5JdpxhngM9HwbqfEXzKy/wK4vUB7STs=
github.com/trustwallet/go-primitives v0.0.19 h1:IvuzU1tB5u+UpjPkJqPqVvb8axLj1LI5nQmTvhmNIck=
github.com/trustwallet/go-primitives v0.0.19/go.mod h1:jLqd7rm+4EYG5JdpxhngM9HwbqfEXzKy/wK4vUB7STs=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=

View File

@ -1,6 +1,9 @@
package processor
import "github.com/trustwallet/assets/internal/file"
import (
"github.com/trustwallet/assets/internal/file"
"github.com/trustwallet/go-primitives/types"
)
type (
Validator struct {
@ -29,14 +32,14 @@ type (
}
TokenItem struct {
Asset string `json:"asset"`
Type string `json:"type"`
Address string `json:"address"`
Name string `json:"name"`
Symbol string `json:"symbol"`
Decimals uint `json:"decimals"`
LogoURI string `json:"logoURI"`
Pairs []Pair `json:"pairs"`
Asset string `json:"asset"`
Type types.TokenType `json:"type"`
Address string `json:"address"`
Name string `json:"name"`
Symbol string `json:"symbol"`
Decimals uint `json:"decimals"`
LogoURI string `json:"logoURI"`
Pairs []Pair `json:"pairs"`
}
Pair struct {

View File

@ -12,62 +12,51 @@ func NewService(fileProvider *file.Service) *Service {
return &Service{fileService: fileProvider}
}
func (s *Service) GetValidator(f *file.AssetFile) *Validator {
func (s *Service) GetValidator(f *file.AssetFile) []Validator {
switch f.Type() {
case file.TypeRootFolder:
return &Validator{
Name: "Root folder contains only allowed files",
Run: s.ValidateRootFolder,
return []Validator{
{Name: "Root folder contains only allowed files", Run: s.ValidateRootFolder},
}
case file.TypeChainFolder:
return &Validator{
Name: "Chain folders are lowercase and contains only allowed files",
Run: s.ValidateChainFolder,
return []Validator{
{Name: "Chain folders are lowercase and contains only allowed files", Run: s.ValidateChainFolder},
}
case file.TypeChainLogoFile, file.TypeAssetLogoFile, file.TypeValidatorsLogoFile, file.TypeDappsLogoFile:
return &Validator{
Name: "Logos (size, dimension)",
Run: s.ValidateImage,
return []Validator{
{Name: "Logos (size, dimension)", Run: s.ValidateImage},
}
case file.TypeAssetFolder:
return &Validator{
Name: "Each asset folder has valid asset address and contains logo/info",
Run: s.ValidateAssetFolder,
return []Validator{
{Name: "Each asset folder has valid asset address and contains logo/info", Run: s.ValidateAssetFolder},
}
case file.TypeDappsFolder:
return &Validator{
Name: "Dapps folder (allowed only png files, lowercase)",
Run: s.ValidateDappsFolder,
return []Validator{
{Name: "Dapps folder (allowed only png files, lowercase)", Run: s.ValidateDappsFolder},
}
case file.TypeAssetInfoFile:
return &Validator{
Name: "Asset info (is valid json, fields)",
Run: s.ValidateAssetInfoFile,
return []Validator{
{Name: "Asset info (is valid json, fields)", Run: s.ValidateAssetInfoFile},
}
case file.TypeChainInfoFile:
return &Validator{
Name: "Chain Info (is valid json, fields)",
Run: s.ValidateChainInfoFile,
return []Validator{
{Name: "Chain Info (is valid json, fields)", Run: s.ValidateChainInfoFile},
}
case file.TypeValidatorsListFile:
return &Validator{
Name: "Validators list file",
Run: s.ValidateValidatorsListFile,
return []Validator{
{Name: "Validators list file", Run: s.ValidateValidatorsListFile},
}
case file.TypeTokenListFile:
return &Validator{
Name: "Token list (if assets from list present in chain)",
Run: s.ValidateTokenListFile,
return []Validator{
{Name: "Token list (if assets from list present in chain)", Run: s.ValidateTokenListFile},
}
case file.TypeChainInfoFolder:
return &Validator{
Name: "Chain Info Folder (has files)",
Run: s.ValidateInfoFolder,
return []Validator{
{Name: "Chain Info Folder (has files)", Run: s.ValidateInfoFolder},
}
case file.TypeValidatorsAssetFolder:
return &Validator{
Name: "Validators asset folder (has logo, valid asset address)",
Run: s.ValidateValidatorsAssetFolder,
return []Validator{
{Name: "Validators asset folder (has logo, valid asset address)", Run: s.ValidateValidatorsAssetFolder},
}
}
@ -75,53 +64,33 @@ func (s *Service) GetValidator(f *file.AssetFile) *Validator {
}
func (s *Service) GetFixers(f *file.AssetFile) []Fixer {
infoFixer := Fixer{
Name: "Formatting all info.json files",
jsonFixer := Fixer{
Name: "Formatting all json files",
Run: s.FixJSON,
}
ethAssetFixer := Fixer{
Name: "Renaming EVM's asset folder to valid address checksum",
Run: s.FixETHAddressChecksum,
}
logoFixer := Fixer{
Name: "Resizing and compressing logo images",
Run: s.FixLogo,
}
chainInfoFixer := Fixer{
Name: "Fixing chain info.json files",
Run: s.FixChainInfoJSON,
}
assetInfoFixer := Fixer{
Name: "Fixing asset info.json files",
Run: s.FixAssetInfoJSON,
}
switch f.Type() {
case file.TypeChainInfoFile:
return []Fixer{
infoFixer,
chainInfoFixer,
jsonFixer,
{Name: "Fixing chain info.json files", Run: s.FixChainInfoJSON},
}
case file.TypeAssetInfoFile:
return []Fixer{
infoFixer,
assetInfoFixer,
jsonFixer,
{Name: "Fixing asset info.json files", Run: s.FixAssetInfoJSON},
}
case file.TypeValidatorsListFile:
return []Fixer{
infoFixer,
jsonFixer,
}
case file.TypeAssetFolder:
return []Fixer{
ethAssetFixer,
{Name: "Renaming EVM's asset folder to valid address checksum", Run: s.FixETHAddressChecksum},
}
case file.TypeChainLogoFile, file.TypeAssetLogoFile, file.TypeValidatorsLogoFile, file.TypeDappsLogoFile:
return []Fixer{
logoFixer,
{Name: "Resizing and compressing logo images", Run: s.FixLogo},
}
}
@ -130,22 +99,13 @@ func (s *Service) GetFixers(f *file.AssetFile) []Fixer {
func (s *Service) GetUpdatersAuto() []Updater {
return []Updater{
{
Name: "Retrieving missing token images, creating binance token list.",
Run: s.UpdateBinanceTokens,
},
{Name: "Retrieving missing token images, creating binance token list.", Run: s.UpdateBinanceTokens},
}
}
func (s *Service) GetUpdatersManual() []Updater {
return []Updater{
{
Name: "Update tokenlist.json for Ethereum",
Run: s.UpdateEthereumTokenlist,
},
{
Name: "Update tokenlist.json for Smartchain",
Run: s.UpdateSmartchainTokenlist,
},
{Name: "Update tokenlist.json for Ethereum", Run: s.UpdateEthereumTokenlist},
{Name: "Update tokenlist.json for Smartchain", Run: s.UpdateSmartchainTokenlist},
}
}

View File

@ -230,7 +230,7 @@ func generateTokenList(marketPairs []binance.MarketPair, tokenList binance.Token
tokenItems = append(tokenItems, TokenItem{
Asset: getAssetIDSymbol(token.Symbol, coin.Coins[coin.BINANCE].Symbol, coin.BINANCE),
Type: getTokenType(token.Symbol, coin.Coins[coin.BINANCE].Symbol, string(types.BEP2)),
Type: getTokenType(token.Symbol, coin.Coins[coin.BINANCE].Symbol, types.BEP2),
Address: token.Symbol,
Name: token.Name,
Symbol: token.OriginalSymbol,
@ -259,9 +259,9 @@ func getAssetIDSymbol(tokenID string, nativeCoinID string, coinType uint) string
return assetlib.BuildID(coinType, tokenID)
}
func getTokenType(symbol string, nativeCoinSymbol string, tokenType string) string {
func getTokenType(symbol string, nativeCoinSymbol string, tokenType types.TokenType) types.TokenType {
if symbol == nativeCoinSymbol {
return "coin"
return types.Coin
}
return tokenType

View File

@ -288,7 +288,7 @@ func getTokenInfoFromSubgraphToken(chain coin.Coin, token *TokenInfo) (*TokenIte
return &TokenItem{
Asset: getAssetIDSymbol(checksum, chain.Symbol, chain.ID),
Type: tokenType,
Type: types.TokenType(tokenType),
Address: checksum,
Name: token.Name,
Symbol: token.Symbol,

View File

@ -14,6 +14,7 @@ import (
"github.com/trustwallet/assets/internal/config"
"github.com/trustwallet/assets/internal/file"
"github.com/trustwallet/go-primitives/coin"
"github.com/trustwallet/go-primitives/types"
)
func (s *Service) ValidateRootFolder(f *file.AssetFile) error {
@ -352,6 +353,65 @@ func (s *Service) ValidateTokenListFile(f *file.AssetFile) error {
return err
}
var model TokenList
err = json.Unmarshal(buf.Bytes(), &model)
if err != nil {
return err
}
err = compareTokenlistWithAssets(model.Tokens, f.Chain().Handle)
if err != nil {
return err
}
return nil
}
func compareTokenlistWithAssets(tokens []TokenItem, chain string) error {
compErr := validation.NewErrComposite()
for _, token := range tokens {
if token.Type == types.Coin {
continue
}
assetPath := path.GetAssetInfoPath(chain, token.Address)
infoFile, err := os.Open(assetPath)
if err != nil {
return err
}
buf := bytes.NewBuffer(nil)
if _, err = buf.ReadFrom(infoFile); err != nil {
return err
}
infoFile.Close()
var infoAsset info.AssetModel
err = json.Unmarshal(buf.Bytes(), &infoAsset)
if err != nil {
return err
}
if string(token.Type) != *infoAsset.Type {
compErr.Append(fmt.Errorf("field type differs from %s", assetPath))
}
if token.Symbol != *infoAsset.Symbol {
compErr.Append(fmt.Errorf("field symbol differs from %s", assetPath))
}
if token.Decimals != uint(*infoAsset.Decimals) {
compErr.Append(fmt.Errorf("field decimals differs from %s", assetPath))
}
}
if compErr.Len() > 0 {
return compErr
}
return nil
}

View File

@ -32,9 +32,9 @@ func (s *Service) RunJob(paths []string, job func(*file.AssetFile)) {
}
func (s *Service) Check(f *file.AssetFile) {
validator := s.processorService.GetValidator(f)
validators := s.processorService.GetValidator(f)
if validator != nil {
for _, validator := range validators {
if err := validator.Run(f); err != nil {
s.handleError(err, f, validator.Name)
}