mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2024-11-19 18:11:36 +01:00
108 lines
31 KiB
C#
108 lines
31 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Net.Http;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using BTCPayServer.Rating;
|
|
using Newtonsoft.Json.Linq;
|
|
|
|
namespace BTCPayServer.Services.Rates
|
|
{
|
|
public class CoinGeckoRateProvider : IRateProvider
|
|
{
|
|
public const string CoinGeckoName = "coingecko";
|
|
// https://api.coingecko.com/api/v3/exchanges/list
|
|
internal static readonly string SupportedExchanges = "[{\"id\":\"1bch\",\"name\":\"1BCH\"},{\"id\":\"aave\",\"name\":\"Aave\"},{\"id\":\"aax\",\"name\":\"AAX\"},{\"id\":\"aax_futures\",\"name\":\"AAX Futures\"},{\"id\":\"abcc\",\"name\":\"ABCC\"},{\"id\":\"acdx\",\"name\":\"ACDX\"},{\"id\":\"acdx_futures\",\"name\":\"ACDX Futures\"},{\"id\":\"acsi_finance\",\"name\":\"Acsi Finance\"},{\"id\":\"aex\",\"name\":\"AEX\"},{\"id\":\"agora_swap\",\"name\":\"Agora Swap\"},{\"id\":\"algebra_finance\",\"name\":\"Algebra finance\"},{\"id\":\"allcoin\",\"name\":\"Allcoin\"},{\"id\":\"alpha_five\",\"name\":\"Alpha5\"},{\"id\":\"altcointrader\",\"name\":\"AltcoinTrader\"},{\"id\":\"alterdice\",\"name\":\"AlterDice\"},{\"id\":\"altmarkets\",\"name\":\"Altmarkets\"},{\"id\":\"anyswap\",\"name\":\"Anyswap\"},{\"id\":\"apeswap\",\"name\":\"ApeSwap\"},{\"id\":\"apeswap_polygon\",\"name\":\"ApeSwap (Polygon)\"},{\"id\":\"aprobit\",\"name\":\"Aprobit\"},{\"id\":\"artisturba\",\"name\":\"Artis Turba\"},{\"id\":\"astroport\",\"name\":\"Astroport\"},{\"id\":\"atomars\",\"name\":\"Atomars\"},{\"id\":\"auroraswap\",\"name\":\"AuroraSwap\"},{\"id\":\"autoshark_finance\",\"name\":\"AutoShark Finance\"},{\"id\":\"azbit\",\"name\":\"Azbit\"},{\"id\":\"b2bx\",\"name\":\"B2BX\"},{\"id\":\"baguette\",\"name\":\"Baguette\"},{\"id\":\"bakeryswap\",\"name\":\"Bakeryswap\"},{\"id\":\"bakkt\",\"name\":\"Bakkt\"},{\"id\":\"balanced_network\",\"name\":\"Balanced Network\"},{\"id\":\"balancer\",\"name\":\"Balancer (v2)\"},{\"id\":\"balancer_arbitrum\",\"name\":\"Balancer (Arbitrum)\"},{\"id\":\"balancer_polygon\",\"name\":\"Balancer (Polygon)\"},{\"id\":\"balancer_v1\",\"name\":\"Balancer (v1)\"},{\"id\":\"bamboo_relay\",\"name\":\"Bamboo Relay\"},{\"id\":\"bancor\",\"name\":\"Bancor Network\"},{\"id\":\"basefex\",\"name\":\"BaseFEX\"},{\"id\":\"bcex\",\"name\":\"BCEX\"},{\"id\":\"beamswap\",\"name\":\"Beamswap\"},{\"id\":\"beaxy\",\"name\":\"Beaxy\"},{\"id\":\"beethovenx\",\"name\":\"Beethoven X\"},{\"id\":\"benswap_smart_bitcoin_cash\",\"name\":\"Benswap\"},{\"id\":\"bgogo\",\"name\":\"Bgogo\"},{\"id\":\"bibo\",\"name\":\"Bibo\"},{\"id\":\"bibox\",\"name\":\"Bibox\"},{\"id\":\"bibox_futures\",\"name\":\"Bibox (Futures)\"},{\"id\":\"biconomy\",\"name\":\"Biconomy\"},{\"id\":\"bidesk\",\"name\":\"Bidesk\"},{\"id\":\"bigone\",\"name\":\"BigONE\"},{\"id\":\"bigone_futures\",\"name\":\"BigONE Futures\"},{\"id\":\"bilaxy\",\"name\":\"Bilaxy\"},{\"id\":\"binance\",\"name\":\"Binance\"},{\"id\":\"binance_dex\",\"name\":\"Binance DEX\"},{\"id\":\"binance_dex_mini\",\"name\":\"Binance DEX (Mini)\"},{\"id\":\"binance_futures\",\"name\":\"Binance (Futures)\"},{\"id\":\"binance_jersey\",\"name\":\"Binance Jersey\"},{\"id\":\"binance_us\",\"name\":\"Binance US\"},{\"id\":\"bingx\",\"name\":\"BingX\"},{\"id\":\"bione\",\"name\":\"BiONE\"},{\"id\":\"birake\",\"name\":\"Birake\"},{\"id\":\"bisq\",\"name\":\"Bisq\"},{\"id\":\"biswap\",\"name\":\"Biswap\"},{\"id\":\"bit2c\",\"name\":\"Bit2c\"},{\"id\":\"bitalong\",\"name\":\"Bitalong\"},{\"id\":\"bitazza\",\"name\":\"Bitazza\"},{\"id\":\"bitbank\",\"name\":\"Bitbank\"},{\"id\":\"bitbay\",\"name\":\"Zonda\"},{\"id\":\"bitbns\",\"name\":\"BitBNS\"},{\"id\":\"bitbox\",\"name\":\"BITFRONT\"},{\"id\":\"bitci\",\"name\":\"Bitci\"},{\"id\":\"bitcoin_com\",\"name\":\"FMFW.io\"},{\"id\":\"bit_com\",\"name\":\"Bit.com\"},{\"id\":\"bit_com_futures\",\"name\":\"Bit.com (Futures)\"},{\"id\":\"bitcratic\",\"name\":\"Bitcratic\"},{\"id\":\"bitexbook\",\"name\":\"BITEXBOOK\"},{\"id\":\"bitexen\",\"name\":\"Bitexen\"},{\"id\":\"bitexlive\",\"name\":\"Bitexlive\"},{\"id\":\"bitfex\",\"name\":\"Bitfex\"},{\"id\":\"bitfinex\",\"name\":\"Bitfinex\"},{\"id\":\"bitfinex_futures\",\"name\":\"Bitfinex (Futures)\"},{\"id\":\"bitflyer\",\"name\":\"bitFlyer\"},{\"id\":\"bitflyer_futures\",\"name\":\"Bitflyer (Futures)\"},{\"id\":\"bitforex\",\"name\":\"Bitforex\"},{\"id\":\"bitforex_futures\",\"name\":\"Bitforex (Futures)\"},{\"id\":\"bitget\",\"name\":\"Bitget\"},{\"id\":\"bitget_futures\",\"name\":\"Bitget Futures\"},{\"id\":\"bithash\",\"name\":\"BitHash\"},{\"id\":\"bitholic\",\"name\":\"Bithumb Singapore\"},{\"id\":\"bithumb\",\"name\":\"Bithumb\"},{\"id\":\"bithumb_futures\",\"name\":\"Bithumb (Futures)\"},{\"id\":\"bithumb_global\",\"name\":\"BitGlobal\"},{\"id\":\"bitinfi\",\"name\":\"Bitinfi\"},{\"id\":\"bitinka\",\"name\":\"Bitinka.com\"},{\"id\":\"bitkonan\",\"name\":\"BitKonan\"},{\"id\":\"bitkub\",\"name\":\"Bitkub\"},{\"id\":\"bitmart\",\"name\":\"BitMart\"},{\"id\":\"bitmax\",\"name\":\"AscendEX (BitMax)\"},{\"id\":\"bitmax_futures\",\"name\":\"AscendEX (BitMax) (Futures)\"},{\"id\":\"bitmesh\",\"name\":\"Bitmesh\"},{\"id\":\"bitmex\",\"name\":\"BitMEX\"},{\"id\":\"bitoffer\",\"name\":\"Bitoffer\"},{\"id\":\"bitonbay\",\"name\":\"BitOnBay\"},{\"id\":\"bitopro\",\"name\":\"BitoPro\"},{\"id\":\"bitpanda\",\"name\":\"Bitpanda Pro\"},{\"id\":\"bitrabbit\",\"name\":\"BitRabbit\"},{\"id\":\"bitrue\",\"name\":\"Bitrue\"},{\"id\":\"bits_blockchain\",\"name\":\"Bits Blockchain\"},{\"id\":\"bitsdaq\",\"name\":\"Bitsdaq\"},{\"id\":\"bitso\",\"name\":\"Bitso\"},{\"id\":\"bitsonic\",\"name\":\"Bitsonic\"},{\"id\":\"bitstamp\",\"name\":\"Bitstamp\"},{\"id\":\"bitsten\",\"name\":\"Bitsten\"},{\"id\":\"bitstorage\",\"name\":\"BitStorage\"},{\"id\":\"bittrex\",\"name\":\"Bittrex\"},{\"id\":\"bitubu\",\"name\":\"Bitubu Exchange\"},{\"id\":\"bitvavo\",\"name\":\"Bitvavo\"},{\"id\":\"bitz_futures\",\"name\":\"BitZ (Futures)\"},{\"id\":\"bkex\",\"name\":\"BKEX\"},{\"id\":\"bleutrade\",\"name\":\"bleutrade\"},{\"id\":\"blockchain_com\",\"name\":\"Blockchain.com\"},{\"id\":\"blockonix\",\"name\":\"Blockonix\"},{\"id\":\"boa\",\"name\":\"BOA Exchange\"},{\"id\":\"bossswap\",\"name\":\"BossSwap\"},{\"id\":\"braziliex\",\"name\":\"Braziliex\"},{\"id\":\"bscswap\",\"name\":\"BSCswap\"},{\"id\":\"btc_alpha\",\"name\":\"BTC-Alpha\"},{\"id\":\"btcbox\",\"name\":\"BTCBOX\"},{\"id\":\"btcc\",\"name\":\"BTCC\"},{\"id\":\"btcex\",\"name\":\"BTCEX\"},{\"id\":\"btc_exchange\",\"name\":\"Btc Exchange\"},{\"id\":\"btcex_futures\",\"name\":\"BTCEX (Futures)\"},{\"id\":\"btcmarkets\",\"name\":\"BTCMarkets\"},{\"id\":\"btcmex\",\"name\":\"BTCMEX\"},{\"id\":\"btcnext\",\"name\":\"BTCNEXT\"},{\"id\":\"btcsquare\",\"name\":\"BTCSquare\"},{\"id\":\"btc_trade_ua\",\"name\":\"BTC Trade UA\"},{\"id\":\"btcturk\",\"name\":\"BtcTurk PRO\"},{\"id\":\"btse\",\"name\":\"BTSE\"},{\"id\":\"btse_futures\",\"name\":\"BTSE (Futures)\"},{\"id\":\"buyucoin\",\"name\":\"BuyUcoin\"},{\"id\":\"bvnex\",\"name\":\"Bvnex\"},{\"id\":\"bw\",\"name\":\"BW.com\"},{\"id\":\"bybit\",\"name\":\"Bybit\"},{\"id\":\"bybit_spot\",\"name\":\"Bybit (Spot)\"},{\"id\":\"c2cx\",\"name\":\"C2CX\"},{\"id\":\"catex\",\"name\":\"Catex\"},{\"id\":\"cbx\",\"name\":\"CBX\"},{\"id\":\"ccex\",\"name\":\"C-CEX\"},{\"id\":\"cex\",\"name\":\"CEX.IO\"},{\"id\":\"chainex\",\"name\":\"ChainEX\"},{\"id\":\"changelly\",\"name\":\"Changelly PRO\"},{\"id\":\"cherryswap\",\"name\":\"CherrySwap\"},{\"id\":\"chiliz\",\"name\":\"Chiliz\"},{\"id\":\"citex\",\"name\":\"CITEX\"},{\"id\":\"clipper_ethereum\",\"name\":\"Clipper (Ethereum)\"},{\"id\":\"clipper_polygon\",\"name\":\"Clipper (Polygon)\"},{\"id\":\"cme_futures\",\"name\":\"CME Group\"},{\"id\":\"coinasset\",\"name\":\"CoinAsset\"},{\"id\":\"coinbene\",\"name\":\"CoinBene\"},{\"id\":\"coinbit\",\"name\":\"Coinbit\"},{\"id\":\"coincheck\",\"name\":\"Coincheck\"},{\"id\":\"coindcx\",\"name\":\"CoinDCX\"},{\"id\":\"coindeal\",\"name\":\"Coindeal\"},{\"id\":\"coineal\",\"name\":\"Coineal\"},{\"id\":\"coin_egg\",\"name\":\"CoinEgg\"},{\"id\":\"coinex\",\"name\":\"CoinEx\"},{\"id\":\"coinex_futures\",\"name\":\"CoinEx (Futures)\"},{\"id\":\"coinfalcon\",\"name\":\"Coinfalcon\"},{\"id\":\"coinfield\",\"name\":\"Coinfield\"},{\"id\":\"coinflex\",\"name\":\"CoinFLEX\"},{\"id\":\"coinflex_futures\",\"name\":\"CoinFLEX (Futures)\"},{\"id\":\"coinfloor\",\"name\":\"Coinfloor\"},{\"id\":\"coingi\",\"name\":\"Coingi\"},{\"id\":\"coinhe\",\"name\":\"CoinHe\"},{\"id\":\"coinhub\",\"name\":\"Coinhub\"},{\"id\":\"coinjar\",\"name\":\"CoinJar Exchange\"},{\"id\":\"coinlim\",\"name\":\"Coinlim\"},{\"id\":\"coinlist\",\"name\":\"Coinlist\"},{\"id\":\"coinmargin\",\"name\":\"CoinMargin\"},{\"id\":\"coin_metro\",\"name\":\"Coinmetro\"},{\"id\":\"coinone\",\"name\":\"Coinone\"},{\"id\":\"coinpark\",\"name\":\"Coinpark\"},{\"id\":\"coinplace\",\"name\":\"Coinplace\"},{\"id\":\"coinsbank\",\"name\":\"Coinsbank\"},{\"id\":\"coinsbit\",\"name\":\"Coinsbit\"},{\"id\":\"coinstore\",\"name\":\"Coinstore\"},{\"id\":\"coinsuper\",\"name\":\"Coinsuper\"},{\"id\":\"cointiger\",\"name\":\"CoinTiger\"},{\"id\":\"cointiger_futures\",\"name\":\"CoinTiger (Futures)\"},{\"id\":\"coinxpro\",\"name\":\"COINX.PRO\"},{\"id\":\"coinzo\",\"name\":\"Coinzo\"},{\"id\":\"coinzoom\",\"name\":\"Coinzoom\"},{\"id\":\"comethswap\",\"name\":\"ComethSwap\"},{\"id\":\"c_patex\",\"name\":\"C-Patex\"},{\"id\":\"cpdax\",\"name\":\"CPDAX\"},{\"id\":\"crex24\",\"name\":\"CREX24\"},{\"id\":\"crodex\",\"name\":\"Crodex\"},{\"id\":\"cronaswap\",\"name\":\"Cronaswap\"},{\"id\":\"crxzone\",\"name\":\"CRXzone\"},{\"id\":\"cryptaldash\",\"name\":\"CryptalDash\"},{\"id\":\"cryptlocex\",\"name\":\"Cryptlocex\"},{\"id\":\"crypto_com\",\"name\":\"Crypto.com Exchange\"},{\"id\":\"crypto_com_futures\",\"name\":\"Crypto.com Exchange (Futures)\"},{\"id\":\"cryptology\",\"name\":\"Cryptology\"},{\"id\":\"c_trade\",\"name\":\"C-Trade\"},{\"id\":\"currency\",\"name\":\"Currency.com\"},{\"id\":\"curve\",\"name\":\"Curve Finance\"},{\"id\":\"curve_factory\",\"name\":\"Curve (Factory Pools)\"},{\"id\":\"cybex\",\"name\":\"Cybex DEX\"},{\"id\":\"darb_finance\",\"name\":\"Darb Finance\"},{\"id\":\"darkknight\",\"name\":\"Dark KnightSwap\"},{\"id\":\"daybit\",\"name\":\"Daybit\"},{\"id\":\"dcoin\",\"name\":\"Dcoin\"},{\"id\":\"ddex\",\"name\":\"DDEX\"},{\"id\":\"decoin\",\"name\":\"Decoin\"},{\"id\":\"defichain\",\"name\":\"DeFiChain DEX\"},{\"id\":\"defi_kingdoms\",\"name\":\"Defi Kingdoms\"},{\"id\":\"defi_swap\",\"name\":\"DeFi Swap\"},{\"id\":\"delta_futures\",\"name\":\"Delta Exchange (Futures)\"},{\"id\":\"delta_spot\",\"name\":\"Delta Exchange\"},{\"id\":\"dem_exchange\",\"name\":\"Demex\"},{\"id\":\"deribit\",\"name\":\"Deribit\"},{\"id\":\"deversifi\",\"name\":\"Deversifi \"},{\"id\":\"dexalot\",\"name\":\"Dexalot\"},{\"id\":\"dextrade\",\"name\":\"Dex-Trade\"},{\"id\":\"dfx\",\"name\":\"DFX\"},{\"id\":\"dfx_polygon\",\"name\":\"DFX (Polygon)\"},{\"id\":\"dfyn\",\"name\":\"Dfyn\"},{\"id\":\"digifinex\",\"name\":\"Digifinex\"},{\"id\":\"dmm\",\"name\":\"KyberSwap (Ethereum)\"},{\"id\":\"dmm_avalanche\",\"name\":\"KyberSwap (Avalanche)\"},{\"id\":\"dmm_bsc\",\"name\":\"KyberSwap (BSC)\"},{\"id\":\"dmm_fantom\",\"name\":\"KyberSwap (Fantom)\"},{\"id\":\"dmm_polygon\",\"name\":\"KyberSwap (Polygon)\"},{\"id\":\"dobitrade\",\"name\":\"Dobitrade\"},{\"id\":\"dodo\",\"name\":\"DODO\"},{\"id\":\"dodo_arbitrum\",\"name\":\"Dodo (Arbitrum)\"},{\"id\":\"dodo_bsc\",\"name\":\"Dodo (BSC)\"},{\"id\":\"dodo_polygon\",\"name\":\"Dodo (Polygon)\"},{\"id\":\"dolomite\",\"name\":\"Dolomite\"},{\"id\":\"dove_wallet\",\"name\":\"Dove Wallet\"},{\"id\":\"dragonex\",\"name\":\"DragonEx\"},{\"id\":\"drift_protocol\",\"name\":\"Drift Protocol\"},{\"id\":\"duedex\",\"name\":\"DueDEX\"},{\"id\":\"dydx\",\"name\":\"dYdX\"},{\"id\":\"dydx_perpetual\",\"name\":\"dYdX Perpetual\"},{\"id\":\"ecxx\",\"name\":\"Ecxx\"},{\"id\":\"elk_finance_avax\",\"name\":\"Elk Finance (Avalanche)\"},{\"id\":\"elk_finance_telos\",\"name\":\"Elk Finance (Telos)\"},{\"id\":\"emirex\",\"name\":\"Emirex\"},{\"id\":\"empiredex\",\"name\":\"EmpireDEX\"},{\"id\":\"empiredex_bsc\",\"name\":\"EmpireDEX (BSC)\"},{\"id\":\"equos\",\"name\":\"EQONEX\"},{\"id\":\"equos_perpetual\",\"name\":\"EQONEX (Perpetual)\"},{\"id\":\"eterbase\",\"name\":\"Eterbase\"},{\"id\":\"etherflyer\",\"name\":\"EtherFlyer\"},{\"id\":\"ethex\",\"name\":\"Ethex\"},{\"id\":\"etorox\",\"name\":\"eToroX\"},{\"id\":\"excalibur\",\"name\":\"Excalibur\"},{\"id\":\"exmarkets\",\"name\":\"ExMarkets\"},{\"id\":\"exmo\",\"name\":\"EXMO\"},{\"id\":\"exrates\",\"name\":\"Exrates\"},{\"id\":\"fatbtc\",\"name\":\"FatBTC\"},{\"id\":\"fex\",\"name\":\"FEX\"},{\"id\":\"financex\",\"name\":\"FinanceX\"},{\"id\":\"finexbox\",\"name\":\"FinexBox\"},{\"id\":\"firebird_finance_polygon\",\"name\":\"Firebird Finance (Polygon)\"},{\"id\":\"floatsv\",\"name\":\"Float SV\"},{\"id\":\"flybit\",\"name\":\"Flybit\"},{\"id\":\"forkdelta\",\"name\":\"ForkDelta\"},{\"id\":\"freiexchange\",\"name\":\"Freiexchange\"},{\"id\":\"ftx\",\"name\":\"FTX (Derivatives)\"},{\"id\":\"ftx_spot\",\"name\":\"FTX\"},{\"id\":\"ftx_us\",\"name\":\"FTX.US\"},{\"id\":\"futureswap\",\"name\":\"Futureswap\"},{\"id\":\"fuzz_finance\",\"name\":\"FuzzSwap\"},{\"id\":\"gate\",\"name\":\"Gate.io\"},{\"id\":\"gate_futures\",\"name\":\"Gate.io (Futures)\"},{\"id\":\"gbx\",\"name\":\"Global Blockchain Exchange\"},{\"id\":\"gdac\",\"name\":\"GDAC\"},{\"id\":\"gdax\",\"name\":\"Coinbase Exchange\"},{\"id\":\"gemini\",\"name\":\"Gemini\"},{\"id\":\"getbtc\",\"name\":\"GetBTC\"},{\"id\":\"gmo_japan\",\"name\":\"GMO Japan\"},{\"id\":\"gmo_japan_futures\",\"name\":\"GMO Japan (Futures)\"},{\"id\":\"gobaba\",\"name\":\"Gobaba\"},{\"id\":\"goku\",\"name\":\"GokuMarket\"},{\"id\":\"gopax\",\"name\":\"GoPax\"},{\"id\":\"graviex\",\"name\":\"Graviex\"},{\"id\":\"hades_swap\",\"name\":\"Hades Swap\"},{\"id\":\"hakuswap\",\"name\":\"HakuSwap\"},{\"id\":\"hanbitco\",\"name\":\"Hanbitco\"},{\"id\":\"hbtc\",\"name\":\"BHEX\"},{\"id\":\"hbtc_futures\",\"name\":\"BHEX (Futures)\"},{\"id\":\"hb_top\",\"name\":\"Hb.top\"},{\"id\":\"hitbtc\",\"name\":\"HitBTC\"},{\"id\":\"honeyswap\",\"name\":\"Honeyswap\"},{\"id\":\"honeyswap_polygon\",\"name\":\"Honeyswap (Polygon)\"},{\"id\":\"hoo\",\"name\":\"Hoo.com\"},{\"id\":\"hopex\",\"name\":\"Hopex\"},{\"id\":\"hotbit\",\"name\":\"Hotbit\"},{\"id\":\"hpx\",\"name\":\"HPX\"},{\"id\":\"hubi\",\"name\":\"Hubi\"},{\"id\":\"huckleberry\",\"name\":\"Huckleberry\"},{\"id\":\"huobi\",\"name\":\"Huobi Global\"},{\"id\":\"huobi_dm\",\"name\":\"Huobi Futures\"},{\"id\":\"huobi_id\",\"name\":\"Huobi Indonesia\"},{\"id\":\"huobi_japan\",\"name\":\"Huobi Japan\"},{\"id\":\"huobi_korea\",\"name\":\"Huobi Korea\"},{\"id\":\"huobi_thailand\",\"name\":\"Huobi Thailand\"},{\"id\":\"ice3x\",\"name\":\"Ice3x\"},{\"id\":\"idcm\",\"name\":\"IDCM\"},{\"id\":\"idex\",\"name\":\"Idex\"},{\"id\":\"impossible_finance\",\"name\":\"Impossible Finance\"},{\"id\":\"incorex\",\"name\":\"IncoreX\"},{\"id\":\"independent_reserve\",\"name\":\"Independent Reserve\"},{\"id\":\"indodax\",\"name\":\"Indodax\"},{\"id\":\"infinity_coin\",\"name\":\"Infinity Coin\"},{\"id\":\"injective\",\"name\":\"Injective Pro\"},{\"id\":\"injective_futures\",\"name\":\"Injective Pro (Futures)\"},{\"id\":\"instantbitex\",\"name\":\"Instant Bitex\"},{\"id\":\"iqfinex\",\"name\":\"IQFinex\"},{\"id\":\"islandswap\",\"name\":\"Islandswap\"},{\"id\":\"itbit\",\"name\":\"itBit\"},{\"id\":\"jetswap\",\"name\":\"JetSwap\"},{\"id\":\"jex\",\"name\":\"Binance JEX\"},{\"id\":\"jex_futures\",\"name\":\"Binance JEX (Futures)\"},{\"id\":\"jswap\",\"name\":\"Jswap\"},{\"id\":\"julswap\",\"name\":\"Julswap\"},{\"id\":\"jupiter\",\"name\":\"Jupiter\"},{\"id\":\"justswap\",\"name\":\"SunSwap\"},{\"id\":\"kaidex\",\"name\":\"Kaidex\"},{\"id\":\"kava\",\"name\":\"Kava Swap\"},{\"id\":\"kickex\",\"name\":\"KickEX\"},{\"id\":\"kkcoin\",\"name\":\"KKCoin\"},{\"id\":\"k_kex\",\"name\":\"KKEX\"},{\"id\":\"knightswap\",\"name\":\"KnightSwap\"},{\"id\":\"koinbazar\",\"name\":\"Koinbazar\"},{\"id\":\"korbit\",\"name\":\"Korbit\"},{\"id\":\"kraken\",\"name\":\"Kraken\"},{\"id\":\"kraken_futures\",\"name\":\"Kraken (Futures)\"},{\"id\":\"kucoin\",\"name\":\"KuCoin\"},{\"id\":\"kumex\",\"name\":\"KuCoin Futures\"},{\"id\":\"kuna\",\"name\":\"Kuna Exchange\"},{\"id\":\"kuswap\",\"name\":\"Kuswap\"},{\"id\":\"lakebtc\",\"name\":\"LakeBTC\"},{\"id\":\"latoken\",\"name\":\"LATOKEN\"},{\"id\":\"lbank\",\"name\":\"LBank\"},{\"id\":\"lcx\",\"name\":\"LCX Exchange\"},{\"id\":\"leonicornswap\",\"name\":\"LeonicornSwap\"},{\"id\":\"levinswap_xdai\",\"name\":\"Levinswap (xDai)\"},{\"id\":\"liquid_derivatives\",\"name\":\"Liquid Perpetuals\"},{\"id\":\"localtrade\",\"name\":\"LocalTrade\"},{\"id\":\"loop\",\"name\":\"Loop Markets\"},{\"id\":\"loopring\",\"name\":\"Loopring\"},{\"id\":\"loopring_amm\",\"name\":\"Loopring AMM\"},{\"id\":\"luaswap\",\"name\":\"Luaswap\"},{\"id\":\"lucent\",\"name\":\"Lucent\"},{\"id\":\"lukki\",\"name\":\"Lukki\"},{\"id\":\"luno\",\"name\":\"Luno\"},{\"id\":\"lydia_finance\",\"name\":\"Lydia Finance\"},{\"id\":\"lykke\",\"name\":\"Lykke\"},{\"id\":\"maiar\",\"name\":\"Maiar\"},{\"id\":\"makiswap\",\"name\":\"Makiswap\"},{\"id\":\"mars_ecosystem\",\"name\":\"Mars Ecosystem\"},{\"id\":\"max_maicoin\",\"name\":\"Max Maicoin\"},{\"id\":\"mcdex\",\"name\":\"MCDEX (Arbitrum)\"},{\"id\":\"mcdex_bsc\",\"name\":\"MCDEX (BSC)\"},{\"id\":\"mdex\",\"name\":\"Mdex\"},{\"id\":\"mdex_bsc\",\"name\":\"Mdex BSC\"},{\"id\":\"mercado_bitcoin\",\"name\":\"Mercado Bitcoin\"},{\"id\":\"mercatox\",\"name\":\"Mercatox\"},{\"id\":\"mercuriex\",\"name\":\"MercuriEx\"},{\"id\":\"milkyswap-milkada\",\"name\":\"MilkySwap\"},{\"id\":\"mimo\",\"name\":\"Mimo\"},{\"id\":\"mistswap_smart_bitcoin_cash\",\"name\":\"Mistswap\"},{\"id\":\"mm_finance\",\"name\":\"MM Finance\"},{\"id\":\"mojitoswap\",\"name\":\"MojitoSwap\"},{\"id\":\"morpheus_swap\",\"name\":\"Morpheus Swap\"},{\"id\":\"multi\",\"name\":\"Multi.io\"},{\"id\":\"mxc\",\"name\":\"MEXC Global\"},{\"id\":\"mxc_futures\",\"name\":\"MEXC Global (Futures)\"},{\"id\":\"mycoinstory\",\"name\":\"MCS\"},{\"id\":\"nachoswap\",\"name\":\"NachoSwap\"},{\"id\":\"namebase\",\"name\":\"Namebase\"},{\"id\":\"nami_exchange\",\"name\":\"Nami.Exchange\"},{\"id\":\"nanu_exchange\",\"name\":\"Nanu Exchange\"},{\"id\":\"narkasa\",\"name\":\"Narkasa\"},{\"id\":\"nash\",\"name\":\"Nash\"},{\"id\":\"nearpad\",\"name\":\"NearPAD\"},{\"id\":\"negociecoins\",\"name\":\"Negociecoins\"},{\"id\":\"neraex\",\"name\":\"Neraex\"},{\"id\":\"netswap\",\"name\":\"Netswap\"},{\"id\":\"newdex\",\"name\":\"Newdex\"},{\"id\":\"nexus_mutual\",\"name\":\"Nexus Mutual\"},{\"id\":\"nice_hash\",\"name\":\"NiceHash\"},{\"id\":\"nominex\",\"name\":\"Nominex\"},{\"id\":\"novadax\",\"name\":\"NovaDAX\"},{\"id\":\"oasis_trade\",\"name\":\"OasisDEX\"},{\"id\":\"occamx\",\"name\":\"OccamX\"},{\"id\":\"oceanex\",\"name\":\"Oceanex\"},{\"id\":\"okcoin\",\"name\":\"Okcoin\"},{\"id\":\"okex\",\"name\":\"OKX\"},{\"id\":\"okex_swap\",\"name\":\"OKX (Futures)\"},{\"id\":\"omgfin\",\"name\":\"Omgfin\"},{\"id\":\"omnidex\",\"name\":\"OmniDex\"},{\"id\":\"one_inch\",\"name\":\"1inch\"},{\"id\":\"one_inch_liquidity_protocol\",\"name\":\"1inch Liquidity Protocol\"},{\"id\":\"one_inch_liquidity_protocol_bsc\",\"name\":\"1inch Liquidity Protocol (BSC)\"},{\"id\":\"oolongswap\",\"name\":\"Oolongswap\"},{\"id\":\"openocean_finance\",\"name\":\"OpenOcean\"},{\"id\":\"openswap\",\"name\":\"OpenSwap\"},{\"id\":\"orca\",\"name\":\"Orca\"},{\"id\":\"orderbook\",\"name\":\"Orderbook.io\"},{\"id\":\"osmosis\",\"name\":\"Osmosis\"},{\"id\":\"otcbtc\",\"name\":\"OTCBTC\"},{\"id\":\"ovex\",\"name\":\"Ovex\"},{\"id\":\"p2pb2b\",\"name\":\"P2PB2B\"},{\"id\":\"paintswap\",\"name\":\"Paintswap\"},{\"id\":\"pancakeswap_new\",\"name\":\"PancakeSwap (v2)\"},{\"id\":\"pangolin\",\"name\":\"Pangolin\"},{\"id\":\"pantherswap\",\"name\":\"PantherSwap\"},{\"id\":\"paribu\",\"name\":\"Paribu\"},{\"id\":\"paritex\",\"name\":\"Paritex\"},{\"id\":\"paroexchange\",\"name\":\"Paro Exchange\"},{\"id\":\"paymium\",\"name\":\"Paymium\"},{\"id\":\"pegasys\",\"name\":\"Pegasys\"},{\"id\":\"perpetual_protocol\",\"name\":\"Perpetual Protocol\"},{\"id\":\"phemex\",\"name\":\"Phemex\"},{\"id\":\"phemex_futures\",\"name\":\"Phemex (Futures)\"},{\"id\":\"photonswap\",\"name\":\"PhotonSwap\"},{\"id\":\"pinkswap\",\"name\":\"PinkSwap\"},{\"id\":\"planet_finance\",\"name\":\"Planet Finance\"},{\"id\":\"polkaex_shiden\",\"name\":\"PolkaEx (Shiden)\"},{\"id\":\"polkaswap\",\"name\":\"Polkaswap\"},{\"id\":\"poloniex\",\"name\":\"Poloniex\"},{\"id\":\"poloniex_futures\",\"name\":\"Poloniex Futures\"},{\"id\":\"polycat_finance\",\"name\":\"Polycat Finance\"},{\"id\":\"polydex\",\"name\":\"PolyDEX\"},{\"id\":\"polyient_dex\",\"name\":\"Polyient Dex\"},{\"id\":\"polyzap\",\"name\":\"PolyZap\"},{\"id\":\"powertrade\",\"name\":\"Powertrade\"},{\"id\":\"prime_xbt\",\"name\":\"Prime XBT\"},{\"id\":\"prism\",\"name\":\"Prism Protocol\"},{\"id\":\"probit\",\"name\":\"ProBit Global\"},{\"id\":\"probit_kr\",\"name\":\"Probit (Korea)\"},{\"id\":\"protofi\",\"name\":\"ProtoFi\"},{\"id\":\"puddingswap\",\"name\":\"PuddingSwap\"},{\"id\":\"qtrade\",\"name\":\"qTrade\"},{\"id\":\"quickswap\",\"name\":\"Quickswap\"},{\"id\":\"quipuswap\",\"name\":\"Quipuswap\"},{\"id\":\"quoine\",\"name\":\"Liquid\"},{\"id\":\"radar_relay\",\"name\":\"Radar Relay\"},{\"id\":\"raydium2\",\"name\":\"Raydium\"},{\"id\":\"ref_finance\",\"name\":\"Ref Finance\"},{\"id\":\"resfinex\",\"name\":\"Resfinex\"},{\"id\":\"rfinex\",\"name\":\"Rfinex\"},{\"id\":\"saber\",\"name\":\"Saber\"},{\"id\":\"safe_trade\",\"name\":\"SafeTrade\"},{\"id\":\"sakeswap\",\"name\":\"SakeSwap\"},{\"id\":\"sashimiswap\",\"name\":\"Sashimiswap\"},{\"id\":\"satoexchange\",\"name\":\"SatoExchange\"},{\"id\":\"secondbtc\",\"name\":\"SecondBTC\"},{\"id\":\"secretswap\",\"name\":\"SecretSwap\"},{\"id\":\"serum_dex\",\"name\":\"Serum DEX\"},{\"id\":\"shibaswap\",\"name\":\"Shibaswap\"},{\"id\":\"siennaswap\",\"name\":\"Siennaswap\"},{\"id\":\"sifchain\",\"name\":\"Sifchain\"},{\"id\":\"sinegy\",\"name\":\"SINEGY\"},{\"id\":\"sistemkoin\",\"name\":\"Sistemkoin\"},{\"id\":\"six_x\",\"name\":\"6x\"},{\"id\":\"solarbeam\",\"name\":\"Solarbeam\"},{\"id\":\"solarflare\",\"name\":\"Solarflare\"},{\"id\":\"solidly\",\"name\":\"Solidly\"},{\"id\":\"soulswap\",\"name\":\"Soulswap\"},{\"id\":\"south_xchange\",\"name\":\"SouthXchange\"},{\"id\":\"spiritswap\",\"name\":\"SpiritSwap\"},{\"id\":\"spookyswap\",\"name\":\"SpookySwap\"},{\"id\":\"stake_cube\",\"name\":\"StakeCube Exchange\"},{\"id\":\"standard\",\"name\":\"Standard\"},{\"id\":\"stellar_term\",\"name\":\"StellarTerm\"},{\"id\":\"stellaswap\",\"name\":\"StellaSwap\"},{\"id\":\"stocks_exchange\",\"name\":\"STEX\"},{\"id\":\"stormgain\",\"name\":\"Stormgain\"},{\"id\":\"stormgain_futures\",\"name\":\"Stormgain Futures\"},{\"id\":\"sunswap_v1\",\"name\":\"Sunswap (v1)\"},{\"id\":\"sushiswap\",\"name\":\"Sushiswap\"},{\"id\":\"sushiswap_arbitrum\",\"name\":\"Sushiswap (Arbitrum One)\"},{\"id\":\"sushiswap_avalanche\",\"name\":\"Sushiswap (Avalanche)\"},{\"id\":\"sushiswap_bsc\",\"name\":\"Sushiswap (BSC)\"},{\"id\":\"sushiswap_celo\",\"name\":\"Sushiswap Celo\"},{\"id\":\"sushiswap_fantom\",\"name\":\"Sushiswap (Fantom)\"},{\"id\":\"sushiswap_harmony\",\"name\":\"Sushiswap (Harmony)\"},{\"id\":\"sushiswap_polygon_pos\",\"name\":\"Sushiswap (Polygon POS)\"},{\"id\":\"sushiswap_xdai\",\"name\":\"Sushiswap (xDai)\"},{\"id\":\"swapr_arbitrum\",\"name\":\"Swapr (Arbitrum)\"},{\"id\":\"swapr_ethereum\",\"name\":\"Swapr (Ethereum)\"},{\"id\":\"swapr_xdai\",\"name\":\"Swapr (Xdai)\"},{\"id\":\"switcheo\",\"name\":\"Switcheo\"},{\"id\":\"swop_fi\",\"name\":\"Swop.Fi\"},{\"id\":\"synthetix\",\"name\":\"Kwenta\"},{\"id\":\"tangoswap\",\"name\":\"TangoSwap\"},{\"id\":\"tdax\",\"name\":\"Satang Pro\"},{\"id\":\"templedao\",\"name\":\"TempleDAO\"},{\"id\":\"terraswap\",\"name\":\"Terraswap\"},{\"id\":\"tethys\",\"name\":\"Tethys Finance\"},{\"id\":\"tetuswap\",\"name\":\"Tetuswap\"},{\"id\":\"therocktrading\",\"name\":\"TheRockTrading\"},{\"id\":\"thorswap\",\"name\":\"THORChain\"},{\"id\":\"thorus\",\"name\":\"Thorus\"},{\"id\":\"thorus_moonbeam\",\"name\":\"Thorus (Moonbeam)\"},{\"id\":\"tidebit\",\"name\":\"Tidebit\"},{\"id\":\"tidex\",\"name\":\"Tidex\"},{\"id\":\"tokenize\",\"name\":\"Tokenize\"},{\"id\":\"tokenlon\",\"name\":\"Tokenlon\"},{\"id\":\"tokenomy\",\"name\":\"Tokenomy\"},{\"id\":\"token_sets\",\"name\":\"TokenSets\"},{\"id\":\"tokens_net\",\"name\":\"TokensNet\"},{\"id\":\"toko_crypto\",\"name\":\"TokoCrypto\"},{\"id\":\"tokok\",\"name\":\"TOKOK\"},{\"id\":\"tokpie\",\"name\":\"Tokpie\"},{\"id\":\"tomb_swap_fantom\",\"name\":\"Tomb Swap (Fantom)\"},{\"id\":\"tomodex\",\"name\":\"TomoDEX\"},{\"id\":\"topbtc\",\"name\":\"TopBTC\"},{\"id\":\"trade_ogre\",\"name\":\"TradeOgre\"},{\"id\":\"traderjoe\",\"name\":\"Trader Joe\"},{\"id\":\"trisolaris\",\"name\":\"Trisolaris\"},{\"id\":\"tron_trade\",\"name\":\"TronTrade\"},{\"id\":\"tropical_finance\",\"name\":\"Tropical Finance\"},{\"id\":\"trx_market\",\"name\":\"PoloniDEX\"},{\"id\":\"txbit\",\"name\":\"Txbit\"},{\"id\":\"ubeswap\",\"name\":\"Ubeswap\"},{\"id\":\"unicly\",\"name\":\"Unicly\"},{\"id\":\"uniswap\",\"name\":\"Uniswap (v3)\"},{\"id\":\"uniswap_arbitrum\",\"name\":\"Uniswap (Arbitrum One)\"},{\"id\":\"uniswap_optimism\",\"name\":\"Uniswap (Optimism)\"},{\"id\":\"uniswap_polygon\",\"name\":\"Uniswap (Polygon)\"},{\"id\":\"uniswap_v1\",\"name\":\"Uniswap (v1)\"},{\"id\":\"uniswap_v2\",\"name\":\"Uniswap (v2)\"},{\"id\":\"unnamed\",\"name\":\"Unnamed\"},{\"id\":\"upbit\",\"name\":\"Upbit\"},{\"id\":\"upbit_indonesia\",\"name\":\"Upbit Indonesia \"},{\"id\":\"value_liquid\",\"name\":\"Value Liquid\"},{\"id\":\"value_liquid_bsc\",\"name\":\"vSwap BSC\"},{\"id\":\"vcc\",\"name\":\"VCC Exchange\"},{\"id\":\"vebitcoin\",\"name\":\"Vebitcoin\"},{\"id\":\"velic\",\"name\":\"Velic\"},{\"id\":\"vindax\",\"name\":\"Vindax\"},{\"id\":\"vinex\",\"name\":\"Vinex\"},{\"id\":\"viperswap\",\"name\":\"ViperSwap\"},{\"id\":\"virgox\",\"name\":\"Virgox\"},{\"id\":\"vitex\",\"name\":\"ViteX\"},{\"id\":\"voltage_finance\",\"name\":\"Voltage Finance\"},{\"id\":\"voltswap_meter\",\"name\":\"Voltswap (Meter)\"},{\"id\":\"voltswap_theta\",\"name\":\"Voltswap (Theta)\"},{\"id\":\"vvs\",\"name\":\"VVS Finance\"},{\"id\":\"wagyuswap\",\"name\":\"WagyuSwap\"},{\"id\":\"wannaswap\",\"name\":\"Wannaswap\"},{\"id\":\"wanswap\",\"name\":\"WanSwap\"},{\"id\":\"wault_swap\",\"name\":\"WaultSwap\"},{\"id\":\"waultswap_polygon\",\"name\":\"WaultSwap Polygon\"},{\"id\":\"waves\",\"name\":\"Waves.Exchange\"},{\"id\":\"wazirx\",\"name\":\"WazirX\"},{\"id\":\"whale_ex\",\"name\":\"WhaleEx\"},{\"id\":\"whitebit\",\"name\":\"WhiteBIT\"},{\"id\":\"wigoswap\",\"name\":\"Wigoswap\"},{\"id\":\"wootrade\",\"name\":\"WOO Network\"},{\"id\":\"xcoex\",\"name\":\"XCOEX\"},{\"id\":\"xfutures\",\"name\":\"xFutures\"},{\"id\":\"xt\",\"name\":\"XT.COM\"},{\"id\":\"yobit\",\"name\":\"YoBit\"},{\"id\":\"yoshi_exchange_bsc\",\"name\":\"Yoshi.exchange (BSC)\"},{\"id\":\"yoshi_exchange_ftm\",\"name\":\"Yoshi.exchange (Fantom)\"},{\"id\":\"yunex\",\"name\":\"Yunex.io\"},{\"id\":\"zaif\",\"name\":\"Zaif\"},{\"id\":\"zappy\",\"name\":\"Zappy\"},{\"id\":\"zb\",\"name\":\"ZB\"},{\"id\":\"zbg\",\"name\":\"ZBG\"},{\"id\":\"zbg_futures\",\"name\":\"ZBG Futures\"},{\"id\":\"zbx\",\"name\":\"ZBX\"},{\"id\":\"zebitex\",\"name\":\"Zebitex\"},{\"id\":\"zebpay\",\"name\":\"ZebPay\"},{\"id\":\"zenlink_moonbeam\",\"name\":\"Zenlink (Moonbeam)\"},{\"id\":\"zenlink_moonriver\",\"name\":\"Zenlink (Moonriver)\"},{\"id\":\"zero_ex\",\"name\":\"0x Protocol\"},{\"id\":\"zero_exchange\",\"name\":\"Zero Exchange\"},{\"id\":\"zg\",\"name\":\"ZG.com\"},{\"id\":\"zgtop\",\"name\":\"ZG.TOP\"},{\"id\":\"zilswap\",\"name\":\"ZilSwap\"},{\"id\":\"zipmex\",\"name\":\"Zipmex\"},{\"id\":\"zkswap\",\"name\":\"ZKSwap (v1)\"},{\"id\":\"zkswap_v2\",\"name\":\"ZKSpace\"}]";
|
|
private readonly HttpClient Client;
|
|
|
|
|
|
public string UnderlyingExchange
|
|
{
|
|
get;
|
|
set;
|
|
}
|
|
|
|
public CoinGeckoRateProvider(IHttpClientFactory httpClientFactory)
|
|
{
|
|
if (httpClientFactory == null)
|
|
{
|
|
return;
|
|
;
|
|
}
|
|
Client = httpClientFactory.CreateClient();
|
|
Client.BaseAddress = new Uri("https://api.coingecko.com/api/v3/");
|
|
Client.DefaultRequestHeaders.Add("Accept", "application/json");
|
|
}
|
|
|
|
public virtual Task<PairRate[]> GetRatesAsync(CancellationToken cancellationToken)
|
|
{
|
|
return UnderlyingExchange is null ? GetCoinGeckoRates(cancellationToken) : GetCoinGeckoExchangeSpecificRates(1, cancellationToken);
|
|
}
|
|
|
|
private async Task<PairRate[]> GetCoinGeckoRates(CancellationToken cancellationToken)
|
|
{
|
|
using var resp = await GetWithBackoffAsync("exchange_rates", cancellationToken);
|
|
resp.EnsureSuccessStatusCode();
|
|
return JObject.Parse(await resp.Content.ReadAsStringAsync()).GetValue("rates").Children()
|
|
.Where(token => ((JProperty)token).Name != "btc")
|
|
.Select(token => new PairRate(new CurrencyPair("BTC", ((JProperty)token).Name.ToString()),
|
|
new BidAsk(((JProperty)token).Value["value"].Value<decimal>()))).ToArray();
|
|
}
|
|
|
|
private async Task<HttpResponseMessage> GetWithBackoffAsync(string request, CancellationToken cancellationToken)
|
|
{
|
|
TimeSpan retryWait = TimeSpan.FromSeconds(1);
|
|
retry:
|
|
var resp = await Client.GetAsync(request, cancellationToken);
|
|
if (resp.StatusCode == System.Net.HttpStatusCode.TooManyRequests)
|
|
{
|
|
resp.Dispose();
|
|
if (retryWait < TimeSpan.FromSeconds(60))
|
|
{
|
|
await Task.Delay(retryWait, cancellationToken);
|
|
retryWait = TimeSpan.FromSeconds(retryWait.TotalSeconds * 2);
|
|
goto retry;
|
|
}
|
|
resp.EnsureSuccessStatusCode();
|
|
}
|
|
return resp;
|
|
}
|
|
|
|
private async Task<PairRate[]> GetCoinGeckoExchangeSpecificRates(int page, CancellationToken cancellationToken)
|
|
{
|
|
using var resp = await GetWithBackoffAsync($"exchanges/{UnderlyingExchange}/tickers?page={page}", cancellationToken);
|
|
|
|
resp.EnsureSuccessStatusCode();
|
|
List<PairRate> result = JObject.Parse(await resp.Content.ReadAsStringAsync()).GetValue("tickers")
|
|
.Select(token => new PairRate(new CurrencyPair(token.Value<string>("base"), token.Value<string>("target")),
|
|
new BidAsk(token.Value<decimal>("last")))).ToList();
|
|
if (page == 1 && resp.Headers.TryGetValues("total", out var total) &&
|
|
resp.Headers.TryGetValues("per-page", out var perPage))
|
|
{
|
|
var totalItems = int.Parse(total.First());
|
|
var perPageItems = int.Parse(perPage.First());
|
|
|
|
var totalPages = totalItems / perPageItems;
|
|
if (totalItems % perPageItems != 0)
|
|
{
|
|
totalPages++;
|
|
}
|
|
|
|
var tasks = new List<Task<PairRate[]>>();
|
|
for (int i = 2; i <= totalPages; i++)
|
|
{
|
|
tasks.Add(GetCoinGeckoExchangeSpecificRates(i, cancellationToken));
|
|
}
|
|
|
|
foreach (var t in (await Task.WhenAll(tasks)))
|
|
{
|
|
result.AddRange(t);
|
|
}
|
|
}
|
|
|
|
return result.ToArray();
|
|
}
|
|
}
|
|
}
|