Unverified Commit a1d014b0 authored by Thibaut Sardan's avatar Thibaut Sardan Committed by GitHub
Browse files

Use new token contract's source (#477)

* add script to manually fetch tokens from github.com/ethereum-lists/tokens over IPFS

* remove ts files from linting

* remove ts files from test to fix CI

* WIP token image

* improve token default image

* Test the pipe with hardcoded IPFS addresses

* add comments

* add --use-hardcoded-addresses argument

* shorten things up with a spread

* address comments

* fix test and address comment
parent 9e359b24
Pipeline #34402 passed with stages
in 9 minutes and 43 seconds
......@@ -45,7 +45,7 @@
"preelectron": "yarn build",
"electron": "cd packages/fether-electron && yarn electron",
"lint-files": "./scripts/lint-files.sh",
"lint": "yarn lint-files '**/*.{js,ts}'",
"lint": "yarn lint-files '**/*.js'",
"prepackage": "yarn build",
"package": "cd packages/fether-electron && yarn package",
"release": "cd packages/fether-electron && yarn release",
......@@ -53,7 +53,8 @@
"start-electron": "cd packages/fether-electron && yarn start",
"start-react": "cd packages/fether-react && yarn start",
"start-ui": "cd packages/fether-ui && yarn start",
"test": "semistandard '**/*.{js,ts}' --parser babel-eslint && CI=true lerna run test --parallel"
"test": "semistandard '**/*.js' --parser babel-eslint && CI=true lerna run test --parallel",
"update-tokens": "yarn run ts-node --project scripts/updateTokens/tsconfig.json scripts/updateTokens"
},
"husky": {
"hooks": {
......@@ -71,6 +72,8 @@
"dependencies": {
"download": "^7.1.0",
"node-fetch": "^2.3.0",
"semver": "^5.6.0"
"semver": "^5.6.0",
"ts-node": "^8.0.3",
"typescript": "^3.3.4000"
}
}
}
\ No newline at end of file
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
// This file is part of Parity.
//
// SPDX-License-Identifier: BSD-3-Clause
const Api = require('@parity/api');
const { bytesToHex } = require('@parity/api/lib/util');
const Contracts = require('@parity/contracts').default;
const fs = require('fs');
// A node serving a HTTP server needs to be running at the following port. The
// chain this script is fetching the tokens is the chain which this node
// connects to.
const api = new Api(new Api.Provider.Http('http://127.0.0.1:8545'));
const run = async () => {
const { tokenReg, githubHint } = new Contracts(api);
const chainName = await api.parity.netChain();
console.log(`Fetching all tokens on ${chainName}, please wait...`);
// Create file to write tokens to
const filePath = `src/assets/tokens/${chainName}.json`;
const wstream = fs.createWriteStream(filePath);
// The JSON file will be an array, so we start by opening a bracket
wstream.write('[\n');
const tokenRegContract = await tokenReg.getContract();
const githubHintContract = await githubHint.getContract();
// Get tokenCount to loop through all tokens
const tokenCount = +(await tokenRegContract.instance.tokenCount.call());
for (let i = 0; i < tokenCount; i++) {
// Get token information
const token = await tokenRegContract.instance.token.call({}, [i]);
// Some tokens are empty (unregistered), we skip them
// token[0] is the token address
if (+token[0] === 0) {
continue;
}
// Get image hash of this token (stored inside the metadata)
const imageHash = bytesToHex(
await tokenRegContract.instance.meta.call({}, [i, 'IMG'])
);
// Variable result will contain the line to be added to our final JSON file
const result = {
address: token[0],
decimals: token[2].e, // token[2] gives a BigNumber(100000000), the number of decimals is the exponent
name: token[3],
symbol: token[1]
};
// If there is an imageHash, then we fetch on GithubHint the url of that
// image
if (+imageHash !== 0) {
const [logo] = await githubHintContract.instance.entries.call({}, [
imageHash
]);
result.logo = logo;
}
// Add this line to the buffer
wstream.write(
`${JSON.stringify(result)}${i === tokenCount - 1 ? '' : ','}\n`
);
}
// Close the opening bracket, and then exit
wstream.write(']', () => {
wstream.close();
// Finished, we can exit
console.log(`Wrote ${tokenCount} tokens to ${filePath}.`);
process.exit(0);
});
};
run();
......@@ -19,8 +19,8 @@ import { OnChange } from 'react-final-form-listeners';
import { startWith } from 'rxjs/operators';
import { withProps } from 'recompose';
import { estimateGas } from '../../utils/transaction';
import Debug from '../../utils/debug';
import { estimateGas } from '../../utils/transaction';
import RequireHealthOverlay from '../../RequireHealthOverlay';
import TokenBalance from '../../Tokens/TokensList/TokenBalance';
import TxDetails from './TxDetails';
......
......@@ -3,12 +3,13 @@
//
// SPDX-License-Identifier: BSD-3-Clause
import React, { Component } from 'react';
import { inject } from 'mobx-react';
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { TokenCard } from 'fether-ui';
import { withRouter } from 'react-router-dom';
import defaultTokenImage from '../../../assets/img/tokens/default-token-128x128.jpg';
import withAccount from '../../../utils/withAccount';
import withBalance from '../../../utils/withBalance';
......@@ -38,7 +39,13 @@ class TokenBalance extends Component {
};
render () {
return <TokenCard onClick={this.handleClick} {...this.props} />;
return (
<TokenCard
defaultTokenImage={defaultTokenImage}
onClick={this.handleClick}
{...this.props}
/>
);
}
}
......
......@@ -4,6 +4,7 @@
// SPDX-License-Identifier: BSD-3-Clause
import React, { Component } from 'react';
import RequireHealthOverlay from '../../RequireHealthOverlay';
import TokenBalance from './TokenBalance';
import withTokens from '../../utils/withTokens';
......@@ -14,7 +15,6 @@ class TokensList extends Component {
const { tokensArray } = this.props;
// Show empty token placeholder if tokens have not been loaded yet
const shownArray = tokensArray.length ? tokensArray : [{}];
return (
<RequireHealthOverlay require='sync'>
<div className='window_content'>
......
......@@ -7,6 +7,7 @@ import React, { Component } from 'react';
import { TokenCard } from 'fether-ui';
import { withRouter } from 'react-router-dom';
import defaultTokenImage from '../../assets/img/tokens/default-token-128x128.jpg';
import withTokens from '../../utils/withTokens';
@withRouter
......@@ -29,7 +30,13 @@ class NewTokenItem extends Component {
return (
<li key={token.address}>
<TokenCard balance={null} showBalance={false} token={token}>
<TokenCard
balance={null}
defaultTokenImage={defaultTokenImage}
showBalance={false}
token={token}
{...this.props}
>
<div className='token_buttons'>
{tokens[token.address] ? (
<button
......
......@@ -10,9 +10,9 @@ import { Header } from 'fether-ui';
import light from '@parity/light.js-react';
import { Link } from 'react-router-dom';
import RequireHealthOverlay from '../RequireHealthOverlay';
import Health from '../Health';
import NewTokenItem from './NewTokenItem';
import RequireHealthOverlay from '../RequireHealthOverlay';
import withTokens from '../utils/withTokens';
@withTokens
......
[
{
"address": "0x7314Dc4d7794b5E7894212CA1556ae8e3De58621",
"symbol": "RLC",
"decimals": 9,
"name": "iExec RLC",
"logo": "https://ipfs.io/ipfs/QmcjNqEC4uDyZJBM946Pyrh8murWVkMh9ufBjpt5hPYuZp"
},
{
"address": "0x6f95a3B682F8e9aacC86D057A6DF88A0E68145A8",
"symbol": "ILSC",
"decimals": 2,
"name": "IsraCoin",
"logo": "https://i.imgur.com/I1qkFfm.png"
},
{
"address": "0xa1bAccA0e12D4091Ec1f92e7CaE3394CC9854D3D",
"symbol": "dqr30",
"decimals": 18,
"name": "DQR"
},
{
"address": "0x4C572Fbc03D4A2B683cF4f10ffdcaFD00885E108",
"symbol": "MEWV5",
"decimals": 9,
"name": "MEW V5 Test Token"
},
{
"address": "0x95D7321EdCe519419ba1DbC60A89bAfbF55EAC0D",
"symbol": "*PLASMA",
"decimals": 6,
"name": "*PLASMA"
},
{
"address": "0xFD5a69A1309595FF5121553F52C8A5B2B1B31031",
"symbol": "NONE",
"decimals": 0,
"name": "None"
}
]
\ No newline at end of file
......@@ -13,6 +13,7 @@ export const TokenCard = ({
balance,
children,
decimals,
defaultTokenImage,
showBalance,
token,
...otherProps
......@@ -20,10 +21,17 @@ export const TokenCard = ({
<Card {...otherProps}>
<div className='token'>
<div className='token_icon'>
{token && token.logo ? (
<img alt={token.symbol} src={token.logo} />
{!!token && !!token.logo ? (
<img
alt={token.symbol}
src={token.logo}
onError={ev => {
ev.target.onerror = null;
ev.target.src = defaultTokenImage;
}}
/>
) : (
<Placeholder height={20} width={20} />
<img alt={token.symbol} src={defaultTokenImage} />
)}
</div>
<div className='token_name'>
......@@ -53,6 +61,7 @@ TokenCard.defaultProps = {
TokenCard.propTypes = {
decimals: PropTypes.number.isRequired,
defaultTokenImage: PropTypes.string,
token: PropTypes.shape({
logo: PropTypes.string,
name: PropTypes.string,
......
# Update Tokens Script
This folder contains a script which will fetch all the tokens from https://github.com/ethereum-lists/tokens, and output all the tokens in a nice JSON file.
This entire folder has been taken from https://github.com/MyCryptoHQ/MyCrypto/tree/574c628e6189de5b7848c4c10258bc22f42b337c/scripts. Thank you MyCrypto for this.
Please also see [this PR](https://github.com/MyCryptoHQ/MyCrypto/pull/1247) for a description of this script.
import './update-tokens';
{
"compilerOptions": {
"lib": [
"es2015"
]
}
}
\ No newline at end of file
export interface Creator {
login: string;
id: number;
avatar_url: string;
gravatar_id: string;
url: string;
html_url: string;
followers_url: string;
following_url: string;
gists_url: string;
starred_url: string;
subscriptions_url: string;
organizations_url: string;
repos_url: string;
events_url: string;
received_events_url: string;
type: string;
site_admin: boolean;
}
export interface CommitStatus {
url: string;
id: number;
state: string;
description: string;
target_url: string;
context: string;
created_at: Date;
updated_at: Date;
creator: Creator;
}
export interface Author {
name: string;
email: string;
date: Date;
}
export interface Committer {
name: string;
email: string;
date: Date;
}
export interface Tree {
sha: string;
url: string;
}
export interface Verification {
verified: boolean;
reason: string;
signature?: any;
payload?: any;
}
export interface Commit {
author: Author;
committer: Committer;
message: string;
tree: Tree;
url: string;
comment_count: number;
verification: Verification;
}
export interface Author2 {
login: string;
id: number;
avatar_url: string;
gravatar_id: string;
url: string;
html_url: string;
followers_url: string;
following_url: string;
gists_url: string;
starred_url: string;
subscriptions_url: string;
organizations_url: string;
repos_url: string;
events_url: string;
received_events_url: string;
type: string;
site_admin: boolean;
}
export interface Committer2 {
login: string;
id: number;
avatar_url: string;
gravatar_id: string;
url: string;
html_url: string;
followers_url: string;
following_url: string;
gists_url: string;
starred_url: string;
subscriptions_url: string;
organizations_url: string;
repos_url: string;
events_url: string;
received_events_url: string;
type: string;
site_admin: boolean;
}
export interface Parent {
sha: string;
url: string;
html_url: string;
}
export interface GitCommit {
sha: string;
commit: Commit;
url: string;
html_url: string;
comments_url: string;
author: Author2;
committer: Committer2;
parents: Parent[];
}
export interface Token {
address: string;
symbol: string;
decimals: number;
error?: string | null;
}
export interface RawTokenJSON {
name?: string;
symbol?: string;
address?: string;
decimals?: number | string;
}
export interface ValidatedTokenJSON {
name: string;
symbol: string;
address: string;
decimals: number | string;
logo: tokenLogo;
}
export interface tokenLogo {
src: string;
}
export interface NormalizedTokenJSON {
name: string;
symbol: string;
address: string;
decimals: number;
logo?: string;
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment