diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
new file mode 100644
index 0000000..744dd08
--- /dev/null
+++ b/.github/FUNDING.yml
@@ -0,0 +1,12 @@
+# These are supported funding model platforms
+
+github: [doctorlai] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
+patreon: # Replace with a single Patreon username
+open_collective: # Replace with a single Open Collective username
+ko_fi: # Replace with a single Ko-fi username
+tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
+community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
+liberapay: # Replace with a single Liberapay username
+issuehunt: # Replace with a single IssueHunt username
+otechie: # Replace with a single Otechie username
+custom: ['https://www.buymeacoffee.com/y0BtG5R','https://paypal.me/doctorlai/3'] # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
diff --git a/README.md b/README.md
index 7392ab8..dd64da6 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,20 @@
# CoinTools
-A Chrome Extension that has a few useful tools and graphs for Cryptocurrency
+A [Chrome Extension](https://chrome.google.com/webstore/detail/coin-tools/fmglcggbdcbkpkfapngjobfeakehpcgj) that has a few useful tools and graphs for Cryptocurrency.
+
+
+
+
+# Features
+1. Show Rates from Cryptocurrency to Fiat.
+2. Show Rates from Cryptocurrency to Cryptocurrency.
+3. Show Rates from Fiat to Fiat.
+4. Concurrency/Fiat Converter
+5. Historic Data Rate
+6. News Feed
+7. Ranking Table with Search
+8. Total Market Cap Charts
+9. Top Cryptocurrency Pairs in Exchange.
+10. UI Language Localizations (more than 10 languages) thanks to the [contributors!](https://github.com/DoctorLai/CoinTools/tree/master/lang)
# License
[MIT](https://github.com/DoctorLai/CoinTools/blob/master/LICENSE)
@@ -14,3 +29,6 @@ Github: https://github.com/DoctorLai/CoinTools/
# Chrome Webstore
Install the [CoinTools](https://chrome.google.com/webstore/detail/coin-tools/fmglcggbdcbkpkfapngjobfeakehpcgj) Now!
+
+# Posts
+- [《Steem 指南》之 justyy 在线工具与 API 系列 – 炒币必备 CoinTools](https://justyy.com/archives/6146)
diff --git a/css/custom.css b/css/custom.css
index 85c7eff..25c9501 100644
--- a/css/custom.css
+++ b/css/custom.css
@@ -65,4 +65,31 @@ table.sortable tbody tr:nth-child(2n+1) td {
}
table.sortable th:not(.sorttable_sorted):not(.sorttable_sorted_reverse):not(.sorttable_nosort):after {
content: " \25B4\25BE"
+}
+
+.upupup {
+ background: red;
+ color: yellow;
+ width: 100%;
+ border-radius: 5px;
+}
+
+.downdowndown {
+ background: green;
+ color: white;
+ width: 100%;
+ border-radius: 5px;
+}
+
+.normal {
+ background: gray;
+ color: black;
+ width: 100%;
+ border-radius: 5px;
+}
+
+.sub {
+ color: white;
+ font-size: 10px;
+ font-style: italic;
}
\ No newline at end of file
diff --git a/css/main.css b/css/main.css
new file mode 100644
index 0000000..a82be3e
--- /dev/null
+++ b/css/main.css
@@ -0,0 +1,6 @@
+img.banner {height: 70px}
+.ext-window {width: 800px;}
+.black {background: black; color: white;}
+.yellow {color: yellow;}
+.chart {width: 680px; height: 500px;}
+body {overflow-x: hidden;}
\ No newline at end of file
diff --git a/icon.png b/icon.png
index 648ed0a..ef2b0e0 100644
Binary files a/icon.png and b/icon.png differ
diff --git a/images/average-price.jpg b/images/average-price.jpg
new file mode 100644
index 0000000..06c23df
Binary files /dev/null and b/images/average-price.jpg differ
diff --git a/images/charts.jpg b/images/charts.jpg
new file mode 100644
index 0000000..0ff4e64
Binary files /dev/null and b/images/charts.jpg differ
diff --git a/images/general.jpg b/images/general.jpg
index 2e24d01..988bf8a 100644
Binary files a/images/general.jpg and b/images/general.jpg differ
diff --git a/images/history.jpg b/images/history.jpg
index 6158ff4..38e6976 100644
Binary files a/images/history.jpg and b/images/history.jpg differ
diff --git a/images/icon-128.png b/images/icon-128.png
index f62ef28..cc5fe9f 100644
Binary files a/images/icon-128.png and b/images/icon-128.png differ
diff --git a/images/icon-16.png b/images/icon-16.png
index 4409402..342879c 100644
Binary files a/images/icon-16.png and b/images/icon-16.png differ
diff --git a/images/icon-32.png b/images/icon-32.png
index 399311f..251bc9c 100644
Binary files a/images/icon-32.png and b/images/icon-32.png differ
diff --git a/images/icon-48.png b/images/icon-48.png
index 0f1d807..b9c4a37 100644
Binary files a/images/icon-48.png and b/images/icon-48.png differ
diff --git a/images/icon.jpg b/images/icon.jpg
index a6cffde..68e6d04 100644
Binary files a/images/icon.jpg and b/images/icon.jpg differ
diff --git a/images/icon.png b/images/icon.png
index f62ef28..cc5fe9f 100644
Binary files a/images/icon.png and b/images/icon.png differ
diff --git a/images/linode.jpg b/images/linode.jpg
new file mode 100644
index 0000000..54e94a0
Binary files /dev/null and b/images/linode.jpg differ
diff --git a/images/news-feed.jpg b/images/news-feed.jpg
new file mode 100644
index 0000000..179cedc
Binary files /dev/null and b/images/news-feed.jpg differ
diff --git a/images/news.jpg b/images/news.jpg
new file mode 100644
index 0000000..4fc45f2
Binary files /dev/null and b/images/news.jpg differ
diff --git a/images/pairs.jpg b/images/pairs.jpg
new file mode 100644
index 0000000..d56b677
Binary files /dev/null and b/images/pairs.jpg differ
diff --git a/images/rank.jpg b/images/rank.jpg
index 4b123c1..9cf8c15 100644
Binary files a/images/rank.jpg and b/images/rank.jpg differ
diff --git a/images/settings.jpg b/images/settings.jpg
new file mode 100644
index 0000000..a6fb1ee
Binary files /dev/null and b/images/settings.jpg differ
diff --git a/images/tools.jpg b/images/tools.jpg
new file mode 100644
index 0000000..bd4c5c8
Binary files /dev/null and b/images/tools.jpg differ
diff --git a/images/vultr.jpg b/images/vultr.jpg
new file mode 100644
index 0000000..d159acb
Binary files /dev/null and b/images/vultr.jpg differ
diff --git a/js/coinmarkcap.js b/js/coinmarkcap.js
index e823451..24914da 100644
--- a/js/coinmarkcap.js
+++ b/js/coinmarkcap.js
@@ -16,6 +16,7 @@
let coinmarkcap = {};
coinmarkcap['BTC'] = 'bitcoin';
coinmarkcap['ETH'] = 'ethereum';
+coinmarkcap['HIVE'] = 'hive';
coinmarkcap['XRP'] = 'ripple';
coinmarkcap['BCH'] = 'bitcoin-cash';
coinmarkcap['LTC'] = 'litecoin';
diff --git a/js/cointools.js b/js/cointools.js
index 13191d8..2584fc2 100644
--- a/js/cointools.js
+++ b/js/cointools.js
@@ -17,6 +17,9 @@ const saveSettings = (msgbox = true) => {
settings['convert_from_history'] = $('input#convert_from_history').val();
settings['convert_to_history'] = $('input#convert_to_history').val();
settings['history_limit'] = $('input#history_limit').val();
+ settings['pairs_id'] = $('input#pairs_id').val();
+ settings['ranking_search'] = $('input#ranking_search_id').val();
+ settings['ranking_limit'] = $('input#ranking_limit').val();
chrome.storage.sync.set({
cointools: settings
}, function() {
@@ -136,22 +139,23 @@ const getGeneralData = (currency, dom) => {
}
// get ranking table from coinmarketcap
-const getRankingTable = (currency, dom, limit = 200) => {
+const getRankingTable = (currency, dom, keyword = "", limit = default_ranking_limit) => {
let currency_upper = currency.toUpperCase();
let currency_lower = currency.toLowerCase();
+ keyword = keyword.trim().toLowerCase();
+ if (keyword.length > 0) {
+ // search a coin
+ limit = 99999;
+ }
+ if (limit <= 0) {
+ limit = default_ranking_limit;
+ }
let api = "https://api.coinmarketcap.com/v1/ticker/?limit=" + limit;
if (currency != '') {
api += "&convert=" + currency_upper;
}
logit(get_text("calling", "calling") + " " + api);
dom.html('');
- var up_or_down_img = function(x) {
- if (x >= 0) {
- return "📈" + x;
- } else {
- return "📉" + x;
- }
- }
$.ajax({
type: "GET",
url: api,
@@ -168,6 +172,14 @@ const getRankingTable = (currency, dom, limit = 200) => {
s += '
' + get_text('last_updated', 'Last Updated') + '
';
s += '';
for (let i = 0; i < result.length; i ++) {
+ if (keyword.length > 0) {
+ let id = result[i]['id'].toLowerCase();
+ let name = result[i]['name'].toLowerCase();
+ let symbol = result[i]['symbol'].toLowerCase();
+ if (!(id.includes(keyword) || name.includes(keyword) || symbol.includes(keyword) )) {
+ continue;
+ }
+ }
s += '
';
s += '
';
s += '
' + result[i]['price_usd'] + '
';
@@ -202,12 +214,22 @@ const getRankingTable = (currency, dom, limit = 200) => {
let total = 0;
// 24 hour vol
let total_24 = 0;
- let data_24 = [];
+ let data_24 = [];
+ // total_supply
+ let data_total_supply = [];
+ let total_supply = 0;
+ // circulating supply
+ let data_circulating_supply = [];
+ let total_circulating_supply = 0;
for (let i = 0; i < Math.min(15, result.length); i ++) {
data.push({'coin': result[i]['name'], 'market_cap_usd': result[i]['market_cap_usd']});
data_24.push({'coin': result[i]['name'], '24h_volume_usd': result[i]['24h_volume_usd']});
- total += parseInt(result[i]['market_cap_usd']);
+ data_total_supply.push({'coin': result[i]['name'], 'total_supply': result[i]['total_supply']});
+ data_circulating_supply.push({'coin': result[i]['name'], 'circulating_supply': result[i]['available_supply']});
+ total += parseInt(result[i]['market_cap_usd']);
total_24 += parseInt(result[i]['24h_volume_usd']);
+ total_supply += parseInt(result[i]['total_supply']);
+ total_circulating_supply += parseInt(result[i]['available_supply']);
}
api = "https://api.coinmarketcap.com/v1/global/";
$.ajax({
@@ -247,7 +269,35 @@ const getRankingTable = (currency, dom, limit = 200) => {
"export": {
"enabled": false
}
- });
+ });
+ let chart_total_supply = AmCharts.makeChart( "chart_div_total_supply", {
+ "type": "pie",
+ "theme": "light",
+ "dataProvider": data_total_supply,
+ "startDuration": 0,
+ "valueField": "total_supply",
+ "titleField": "coin",
+ "balloon":{
+ "fixedPosition": true
+ },
+ "export": {
+ "enabled": false
+ }
+ });
+ let chart_circulate_supply = AmCharts.makeChart( "chart_div_circulating_supply", {
+ "type": "pie",
+ "theme": "light",
+ "dataProvider": data_circulating_supply,
+ "startDuration": 0,
+ "valueField": "circulating_supply",
+ "titleField": "coin",
+ "balloon":{
+ "fixedPosition": true
+ },
+ "export": {
+ "enabled": false
+ }
+ });
},
error: function(request, status, error) {
logit(get_text('response', 'Response') + ': ' + request.responseText);
@@ -272,28 +322,113 @@ const getRankingTable = (currency, dom, limit = 200) => {
});
}
-// ajax calling API to return the price of USD for coin
-const getPriceOfUSD = (coin) => {
+// getting conversion from cryptocompare
+const getPriceCC = (a, b) => {
+ a = a.toUpperCase();
+ if (a == 'SBD') {
+ a = 'SBD*';
+ }
+ b = b.toUpperCase();
+ if (b == 'SBD') {
+ b = 'SBD*';
+ }
+ let api = "https://min-api.cryptocompare.com/data/price?fsym=" + a + "&tsyms=" + b;
return new Promise((resolve, reject) => {
- let api = "https://api.coinmarketcap.com/v1/ticker/" + coin + '/';
- fetch(api, {mode: 'cors'}).then(validateResponse).then(readResponseAsJSON).then(function(result) {
- resolve(result[0].price_usd);
+ fetch(api, {mode: 'cors'})
+ .then(validateResponse)
+ .then(readResponseAsJSON)
+ .then(function(result) {
+ if (result[b]) {
+ resolve(result[b]);
+ } else {
+ reject("invalid pairs: " + a + ", " + b);
+ }
}).catch(function(error) {
logit(get_text("request_failed", "Request failed") + ': ' + api + ": " + error);
reject(error);
});
+ });
+}
+
+// ajax calling API to return the price of USD for coin
+const getPriceOfUSD_UsingCoinPaprika = (coin) => {
+ return new Promise((resolve, reject) => {
+ // TODO: try different coin ID
+ let api = "https://api.coinpaprika.com/v1/ticker/" + coin;
+ fetch(api, {mode: 'cors'})
+ .then(validateResponse)
+ .then(readResponseAsJSON)
+ .then(function(result) {
+ if (result.price_usd) {
+ resolve(result.price_usd);
+ } else {
+ reject("error");
+ }
+ }).catch(function(error) {
+ reject(error);
+ });
+ });
+}
+
+// ajax calling API to return the price of USD for coin
+const getPriceOfUSD = (coin) => {
+ return new Promise((resolve, reject) => {
+ coin = coin.toLowerCase();
+ let api = "https://api.coingecko.com/api/v3/simple/price?ids=" + coin + "&vs_currencies=usd";
+ fetch(api, {mode: 'cors'})
+ .then(validateResponse)
+ .then(readResponseAsJSON)
+ .then(function(result) {
+ if (result[coin] && result[coin]["usd"]) {
+ resolve(result[coin]["usd"]);
+ } else {
+ getPriceCC(coin, 'USD').then((res) => {
+ resolve(res);
+ }).catch(function(error) {
+ reject(error);
+ });
+ }
+ }).catch(function(error) {
+ getPriceCC(coin, 'USD').then((res) => {
+ resolve(res);
+ }).catch(function(error) {
+ // try coinpaparika as last resort.
+ getPriceOfUSD_UsingCoinPaprika(coin).then((res) => {
+ resolve(res);
+ }).catch(function(error) {
+ // there is nothing we can do further
+ logit(get_text("request_failed", "Request failed") + ': ' + api + ": " + error);
+ reject(error);
+ });
+ });
+ });
});
}
// ajax calling API to return the price of currency for 1 BTC
const getPriceOf1BTC = (currency) => {
return new Promise((resolve, reject) => {
- let api = "https://api.coinmarketcap.com/v1/ticker/bitcoin/?convert=" + currency.toUpperCase();
- fetch(api, {mode: 'cors'}).then(validateResponse).then(readResponseAsJSON).then(function(result) {
- resolve(result[0]['price_' + currency.toLowerCase()]);
+ let api = "https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=" + currency.toUpperCase();
+ fetch(api, {mode: 'cors'})
+ .then(validateResponse)
+ .then(readResponseAsJSON)
+ .then(function(result) {
+ if (result["bitcoin"] && result["bitcoin"][currency.toLowerCase]) {
+ resolve(result["bitcoin"][currency.toLowerCase]);
+ } else {
+ getPriceCC('BTC', currency).then((res) => {
+ resolve(res);
+ }).catch(function(error) {
+ reject(error);
+ });
+ }
}).catch(function(error) {
- logit(get_text("request_failed", "Request failed") + ': ' + api + ": " + error);
- reject(error);
+ getPriceCC('BTC', currency).then((res) => {
+ resolve(res);
+ }).catch(function(error) {
+ logit(get_text("request_failed", "Request failed") + ': ' + api + ": " + error);
+ reject(error);
+ });
});
});
}
@@ -301,12 +436,28 @@ const getPriceOf1BTC = (currency) => {
// ajax calling API to return the price of USD for coin
const getPriceOf = (coin, fiat) => {
return new Promise((resolve, reject) => {
- let api = "https://api.coinmarketcap.com/v1/ticker/" + coin + '/?convert=' + fiat.toUpperCase();
- fetch(api, {mode: 'cors'}).then(validateResponse).then(readResponseAsJSON).then(function(result) {
- resolve(result[0]['price_' + fiat.toLowerCase()]);
+ coin = coin.toLowerCase();
+ let api = "https://api.coingecko.com/api/v3/simple/price?ids=" + coin + "&vs_currencies=" + fiat.toUpperCase();
+ fetch(api, {mode: 'cors'})
+ .then(validateResponse)
+ .then(readResponseAsJSON)
+ .then(function(result) {
+ if (result[coin] && result[coin][fiat.toLowerCase]) {
+ resolve(result[coin][fiat.toLowerCase]);
+ } else {
+ getPriceCC(coin, fiat).then((res) => {
+ resolve(res);
+ }).catch(function(error) {
+ reject(error);
+ });
+ }
}).catch(function(error) {
- logit(get_text("request_failed", "Request failed") + ': ' + api + ": " + error);
- reject(error);
+ getPriceCC(coin, fiat).then((res) => {
+ resolve(res);
+ }).catch(function(error) {
+ logit(get_text("request_failed", "Request failed") + ': ' + api + ": " + error);
+ reject(error);
+ });
});
});
}
@@ -315,12 +466,28 @@ const getPriceOf = (coin, fiat) => {
const getPriceOf_Coinbase_Fiat = (a, b) => {
return new Promise((resolve, reject) => {
let api = 'https://api.coinbase.com/v2/exchange-rates/?currency=' + a.toUpperCase();
- fetch(api, {mode: 'cors'}).then(validateResponse).then(readResponseAsJSON).then(function(result) {
+ fetch(api, {mode: 'cors'})
+ .then(validateResponse)
+ .then(readResponseAsJSON)
+ .then(function(result) {
let data = result.data.rates;
- resolve(data[b.toUpperCase()]);
+ let key = b.toUpperCase();
+ if (data[key]) {
+ resolve(data[key]);
+ } else {
+ getPriceCC(a, b).then((res) => {
+ resolve(res);
+ }).catch(function(error) {
+ reject(error);
+ });
+ }
}).catch(function(error) {
- logit(get_text("request_failed", "Request failed") + ': ' + api + ": " + error);
- reject(error);
+ getPriceCC(a, b).then((res) => {
+ resolve(res);
+ }).catch(function(error) {
+ logit(get_text("request_failed", "Request failed") + ': ' + api + ": " + error);
+ reject(error);
+ });
});
});
}
@@ -451,6 +618,7 @@ const processConversion = (s, local_currency = '') => {
}
} else if (pair.length == 1) {
let a = pair[0].trim().toUpperCase();
+ let b = a;
let currency = $('select#currency').val();
var pat = /^[a-zA-Z\-]+$/;
if (pat.test(a)) {
@@ -459,11 +627,39 @@ const processConversion = (s, local_currency = '') => {
}
// if it is a fiat currency
if (isFiat(a)) {
- let api = 'https://api.coinbase.com/v2/exchange-rates/?currency=' + a.toUpperCase();
- fetch(api, {mode: 'cors'}).then(validateResponse).then(readResponseAsJSON).then(function(result) {
- $('textarea#convert_result').append(getFiatReport(result, a, currency));
+ let key = a.toUpperCase();
+ let api = 'https://api.coinbase.com/v2/exchange-rates/?currency=' + key;
+ fetch(api, {mode: 'cors'})
+ .then(validateResponse)
+ .then(readResponseAsJSON)
+ .then(function(result) {
+ if (result) {
+ let dom = $('div#conversion_results');
+ let dom_id = "convert" + random_id();
+ dom.append('
');
+ $('textarea#convert_result').append(getFiatReport(result, a, currency));
+ $('div#' + dom_id).html("
1 " + a + " = " + res + " " + currency + "
");
+ } else {
+ getPriceCC(key, currency).then((res) => {
+ let dom = $('div#conversion_results');
+ let dom_id = "convert" + random_id();
+ dom.append('