diff --git a/demo/src/demos/assets/index.js b/demo/src/demos/assets/index.js new file mode 100644 index 0000000000..adde2a6d7c --- /dev/null +++ b/demo/src/demos/assets/index.js @@ -0,0 +1,197 @@ +// @flow +import React, { Component, useEffect, useState, useMemo } from "react"; +import ReactTable from "react-table"; +import { BigNumber } from "bignumber.js"; +import uniqWith from "lodash/uniqWith"; +import { + listTokens, + listCryptoCurrencies, + isCurrencySupported, + getCryptoCurrencyById, + getFiatCurrencyByTicker, + useCurrenciesByMarketcap, + useMarketcapTickers, + formatCurrencyUnit +} from "@ledgerhq/live-common/lib/currencies"; +import { + getDailyRatesBatched, + formatCounterValueDay +} from "@ledgerhq/live-common/lib/countervalues"; + +const usdFiat = getFiatCurrencyByTicker("USD"); +const bitcoin = getCryptoCurrencyById("bitcoin"); +const ethereum = getCryptoCurrencyById("ethereum"); + +const getRates = getDailyRatesBatched(50); + +const columns = [ + { + Header: "Live?", + width: 80, + accessor: "livesupport" + }, + { + Header: "type", + width: 120, + accessor: "typeText" + }, + { + Header: "Name", + accessor: "name" + }, + { + Header: "Ticker", + accessor: "ticker", + width: 100 + }, + { + Header: "extra", + id: "extra", + accessor: token => + token.type === "TokenCurrency" ? ( + + {token.contractAddress} + + ) : ( + "coinType=" + token.coinType + ) + }, + { + id: "countervalue", + Header: p => { + const data = p.data.map(d => d._original); + const supported = data.filter(d => d.countervalueStatus === "yes"); + const withExchange = data.filter(d => d.exchange); + const percentageSupport = supported.length / data.length; + const realPercentageSupport = withExchange.length / data.length; + return ( +
+ countervalue +
+ {supported.length} have marketcap ( + {Math.floor(percentageSupport * 1000) / 10}%) +
+
+ {withExchange.length} supported ( + {Math.floor(realPercentageSupport * 1000) / 10}%) +
+
+ ); + }, + accessor: "countervalueText" + } +]; + +const counterpartFor = c => + c === bitcoin ? usdFiat : c.type === "CryptoCurrency" ? bitcoin : ethereum; + +const Assets = () => { + const tokens = listTokens(); + const currencies = listCryptoCurrencies(); + const all = useMemo(() => currencies.concat(tokens), [tokens, currencies]); + const tickers = useMarketcapTickers() || []; + const [rates, setRates] = useState({}); + const byMarketcap = useCurrenciesByMarketcap(all); + const data = byMarketcap.map(t => { + let countervalueStatus = "no"; + let loading = false; + let exchange; + let formatted = ""; + if (t.disableCountervalue) { + countervalueStatus = "disabled"; + } else if (tickers.includes(t.ticker)) { + countervalueStatus = "yes"; + const counter = counterpartFor(t); + if (rates[counter.ticker]) { + const ratePerExchange = (rates[counter.ticker] || {})[t.ticker] || {}; + exchange = Object.keys(ratePerExchange)[0]; + if (exchange) { + const latest = ratePerExchange[exchange].latest || 0; + formatted = formatCurrencyUnit( + counter.units[0], + BigNumber(latest).times(10 ** t.units[0].magnitude), + { + showCode: true + } + ); + } + } else { + loading = true; + } + } + const countervalueText = + countervalueStatus !== "yes" + ? countervalueStatus + : loading + ? "..." + : exchange + ? exchange + " @ " + formatted + : "no exchange found"; + const livesupport = + t.type === "TokenCurrency" || isCurrencySupported(t) ? "yes" : "no"; + return { + ...t, + typeText: + t.type === "TokenCurrency" + ? "token on " + t.parentCurrency.name + : "coin", + countervalueStatus, + countervalueText, + exchange, + loading, + livesupport + }; + }); + + useEffect(() => { + if (!tickers) return; + const afterDay = formatCounterValueDay(new Date()); + getRates( + () => window.LEDGER_CV_API, + uniqWith( + all + .filter(c => tickers.includes(c.ticker)) + .map(from => ({ + from: from.ticker, + to: counterpartFor(from).ticker, + afterDay + })), + (a, b) => a.from === b.from && a.to === b.to + ) + ).then(setRates); + }, [tickers, all]); + + return ( +
+ +
+ ); +}; + +export default class Demo extends Component<{}> { + static demo = { + title: "Assets", + url: "/assets" + }; + render() { + return ; + } +} diff --git a/demo/src/demos/index.js b/demo/src/demos/index.js index 07f527ccc9..412edb66b5 100644 --- a/demo/src/demos/index.js +++ b/demo/src/demos/index.js @@ -9,7 +9,7 @@ import explorers from "./explorers"; import apps from "./apps"; import Partners from "./Partners"; import erc20 from "./erc20"; -import tokens from "./tokens"; +import assets from "./assets"; export default { Countervalues, @@ -23,5 +23,5 @@ export default { explorers, erc20, apps, - tokens + assets }; diff --git a/demo/src/demos/tokens/index.js b/demo/src/demos/tokens/index.js deleted file mode 100644 index c900f61558..0000000000 --- a/demo/src/demos/tokens/index.js +++ /dev/null @@ -1,165 +0,0 @@ -// @flow -import React, { Component, useEffect, useState } from "react"; -import ReactTable from "react-table"; -import uniq from "lodash/uniq"; -import { - listTokens, - useCurrenciesByMarketcap, - useMarketcapTickers -} from "@ledgerhq/live-common/lib/currencies"; -import { - getDailyRatesBatched, - formatCounterValueDay -} from "@ledgerhq/live-common/lib/countervalues"; - -const getRates = getDailyRatesBatched(50); - -const columns = [ - { - Header: "by marketcap", - accessor: null, - maxWidth: 200 - }, - { - Header: "Name", - accessor: "name" - }, - { - Header: "Ticker", - accessor: "ticker" - }, - { - Header: "Smart contract address", - id: "contractAddress", - accessor: token => ( - - {token.contractAddress} - - ) - }, - { - id: "countervalue", - Header: p => { - const data = p.data.map(d => d._original); - const supported = data.filter(d => d.countervalueStatus === "yes"); - const withExchange = data.filter(d => d.exchange && d.ethValue); - const percentageSupport = supported.length / data.length; - const realPercentageSupport = withExchange.length / data.length; - - return ( -
- countervalue -
- {supported.length} have marketcap ( - {Math.floor(percentageSupport * 1000) / 10}%) -
-
- {withExchange.length} supported against ETH ( - {Math.floor(realPercentageSupport * 1000) / 10}%) -
-
- ); - }, - accessor: "countervalueText" - } -]; - -const Tokens = () => { - const tokens = listTokens(); - const tickers = useMarketcapTickers() || []; - const [rates, setRates] = useState({}); - const byMarketcap = useCurrenciesByMarketcap(tokens); - const data = byMarketcap.map(t => { - let countervalueStatus = "no"; - let loading = false; - let exchange; - let ethValue; - if (t.disableCountervalue) { - countervalueStatus = "disabled"; - } else if (tickers.includes(t.ticker)) { - countervalueStatus = "yes"; - if (rates.ETH) { - const ratePerExchange = (rates.ETH || {})[t.ticker] || {}; - exchange = Object.keys(ratePerExchange)[0]; - if (exchange) { - const latest = ratePerExchange[exchange].latest || 0; - const mul = 10 ** (t.units[0].magnitude - 18); - ethValue = latest * mul; - } - } else { - loading = true; - } - } - const countervalueText = - countervalueStatus + - (countervalueStatus !== "yes" - ? "" - : loading - ? "..." - : exchange - ? " @" + - exchange + - " Ξ" + - (ethValue || 0).toLocaleString("en", { - minimumFractionDigits: 0, - maximumFractionDigits: 8 - }) - : " but no exchange"); - return { - ...t, - countervalueStatus, - countervalueText, - ethValue, - exchange, - loading - }; - }); - - useEffect(() => { - if (!tickers) return; - getRates( - () => window.LEDGER_CV_API, - uniq(tickers) - .filter(ticker => tokens.some(t => t.ticker === ticker)) - .map(from => ({ - from, - to: "ETH", - afterDay: formatCounterValueDay(new Date()) - })) - ).then(setRates); - }, [tickers, tokens]); - - return ( -
- -
- ); -}; - -export default class Demo extends Component<{}> { - static demo = { - title: "Tokens", - url: "/Tokens" - }; - render() { - return ; - } -}