github.com/status-im/status-go@v1.1.0/services/wallet/token/downloader/main.go (about)

     1  package main
     2  
     3  import (
     4  	"encoding/json"
     5  	"errors"
     6  	"fmt"
     7  	"html/template"
     8  	"io/ioutil"
     9  	"net/http"
    10  	"os"
    11  	"time"
    12  
    13  	"github.com/status-im/status-go/services/wallet/token"
    14  
    15  	"github.com/xeipuuv/gojsonschema"
    16  )
    17  
    18  const uniswapTokensURL = "https://gateway.ipfs.io/ipns/tokens.uniswap.org" // nolint:gosec
    19  const tokenListSchemaURL = "https://uniswap.org/tokenlist.schema.json"     // nolint:gosec
    20  
    21  const templateText = `
    22  package token
    23  
    24  import (
    25  	"github.com/ethereum/go-ethereum/common"
    26  )
    27  
    28  var uniswapTokens = []*Token{
    29  	{{ range $token := .Tokens }}
    30  	{
    31  		Address:   common.HexToAddress("{{ $token.Address }}"),
    32  		Name:      "{{ $token.Name }}",
    33  		Symbol:    "{{ $token.Symbol }}",
    34  		Decimals:  {{ $token.Decimals }},
    35  		ChainID:   {{ $token.ChainID }},
    36  		PegSymbol: "{{ $token.PegSymbol }}",
    37  	},
    38  	{{ end }}
    39  }
    40  `
    41  
    42  func validateDocument(doc string, schemaURL string) (bool, error) {
    43  	schemaLoader := gojsonschema.NewReferenceLoader(schemaURL)
    44  	docLoader := gojsonschema.NewStringLoader(doc)
    45  
    46  	result, err := gojsonschema.Validate(schemaLoader, docLoader)
    47  	if err != nil {
    48  		return false, err
    49  	}
    50  
    51  	if !result.Valid() {
    52  		return false, errors.New("Token list does not match schema")
    53  	}
    54  
    55  	return true, nil
    56  }
    57  
    58  func bytesToTokens(tokenListData []byte) ([]*token.Token, error) {
    59  	var objmap map[string]json.RawMessage
    60  	err := json.Unmarshal(tokenListData, &objmap)
    61  	if err != nil {
    62  		return nil, err
    63  	}
    64  	var tokens []*token.Token
    65  	err = json.Unmarshal(objmap["tokens"], &tokens)
    66  	if err != nil {
    67  		return nil, err
    68  	}
    69  
    70  	return tokens, nil
    71  }
    72  
    73  func main() {
    74  	client := &http.Client{Timeout: time.Minute}
    75  	response, err := client.Get(uniswapTokensURL)
    76  	if err != nil {
    77  		fmt.Printf("Failed to fetch tokens: %v\n", err)
    78  		return
    79  	}
    80  	defer response.Body.Close()
    81  
    82  	body, err := ioutil.ReadAll(response.Body)
    83  	if err != nil {
    84  		fmt.Printf("Failed to read tokens: %v\n", err)
    85  		return
    86  	}
    87  
    88  	_, err = validateDocument(string(body), tokenListSchemaURL)
    89  	if err != nil {
    90  		fmt.Printf("Failed to validate token list against schema: %v\n", err)
    91  		return
    92  	}
    93  
    94  	tokens, err := bytesToTokens(body)
    95  	if err != nil {
    96  		fmt.Printf("Failed to parse token list: %v\n", err)
    97  		return
    98  	}
    99  
   100  	tmpl := template.Must(template.New("tokens").Parse(templateText))
   101  
   102  	// Create the output Go file
   103  	file, err := os.Create("uniswap.go")
   104  	if err != nil {
   105  		fmt.Printf("Failed to create go file: %v\n", err)
   106  		return
   107  	}
   108  	defer file.Close()
   109  
   110  	// Execute the template with the tokens data and write the result to the file
   111  	err = tmpl.Execute(file, struct{ Tokens []*token.Token }{Tokens: tokens})
   112  	if err != nil {
   113  		fmt.Printf("Failed to write file: %v\n", err)
   114  		return
   115  	}
   116  }