AlphaWallet / alpha-wallet-android

An advanced Ethereum mobile wallet
https://www.alphawallet.com
MIT License
596 stars 530 forks source link

CoinGecko price history #1829

Closed hboon closed 3 years ago

hboon commented 3 years ago

To get the historical data, just do (where "ethereum" is CoinGecko's token id for Ether):

curl 'https://api.coingecko.com/api/v3/coins/ethereum/market_chart?days=7&vs_currency=USD'

You can substitute days for 1, 7, 30, 90, 360 which should match what we need

JamesSmartCell commented 3 years ago

That is epic. Works perfectly.

https://api.coingecko.com/api/v3/coins/dai/market_chart?days=1&vs_currency=USD

For ERC20 did you have to use a lookup table to match token address to api 'coins' name? Or does the symbol work?

hboon commented 3 years ago

We have this. The platform string mapping is generated emprically:

if platformMatches() {
    if contract == "" { //because some don't specify contracts, only ""
        return symbol matches case-insenstively
    } else if contract matches {
        return true
    } else {
        return false
    }
} else {
    return symbol + name matches case-insenstively //need a name match because there are false positives otherwise
}

Mapping table for platforms:

private func platformMatches(_ platform: String, server: RPCServer) -> Bool {
    switch server {
    case .main: return platform == "ethereum"
    case .classic: return platform == "ethereum-classic"
    case .xDai: return platform == "xdai"
    case .binance_smart_chain: return platform == "binance-smart-chain"
    case .avalanche: return platform == "Avalanche"
    case .polygon: return platform == "polygon-pos"
    case .poa, .kovan, .sokol, .callisto, .goerli, .artis_sigma1, .artis_tau1, .binance_smart_chain_testnet, .ropsten, .rinkeby, .heco, .heco_testnet, .fantom, .fantom_testnet, .avalanche_testnet, .mumbai_testnet, .custom:
        return false
    }
}
hboon commented 3 years ago

^ This can be used to build a token contract + server <-> CoinGecko token ID mapping from the results of the /api/v3/coins/list endpoint

JamesSmartCell commented 3 years ago

^ This can be used to build a token contract + server <-> CoinGecko token ID mapping from the results of the /api/v3/coins/list endpoint

So you use that mapping to find a symbol match then use the corresponding 'id' in the api/v3/coins/ route?

EG {"id":"aave-dai","symbol":"adai","name":"Aave DAI"}

Do you need to disambiguate clashing symbols using the full name?

hboon commented 3 years ago

So you use that mapping to find a symbol match then use the corresponding 'id' in the api/v3/coins/ route?

Do you mean api/v3/coins/ethereum/market_chart? Yes. But only if contract matching fails. Didn't check if name matching would give good matches.

JamesSmartCell commented 3 years ago

Contract matching? There's no address in the results I saw. Is there a way to get the addresses? I can only see symbol and name.

hboon commented 3 years ago

It’s in the platforms dictionary. Oh. Maybe you need to set a query parameter to include it when fetching the list of supported tokens. See how it the pseudo code above we compare it.

JamesSmartCell commented 3 years ago

It’s in the platforms dictionary. Oh. Maybe you need to set a query parameter to include it when fetching the list of supported tokens. See how it the pseudo code above we compare it.

What's the actual route to get the addresses? I looked at the pseudo code but couldn't get where you form the route. I tried adding the platform name in but couldn't get any correct response. I can only ever get symbol/name for the tokens from the /api/v3/coins/list mapping.

hboon commented 3 years ago

There are 3 endpoints involved:

A. Fetch CoinGecko token IDs for supported tokens: curl 'https://api.coingecko.com/api/v3/coins/list?include_platform=true'

B. Fetch token prices given a list of token IDs: curl 'https://api.coingecko.com/api/v3/coins/markets?ids=ethereum%2Cweth%2Csai%2Cuniswap%2Camber%2Ctether%2Ckickico%2Cusd-coin%2Cdai%2Cwaifu-token%2Chuobi-token%2Cscatter-cx%2Cnest%2Cntoken0031%2C0x&page=1&per_page=250&price_change_percentage=24h&vs_currency=USD'

C. Fetch chart history given 1 token ID: curl 'https://api.coingecko.com/api/v3/coins/ethereum/market_chart?days=7&vs_currency=USD'

(A) Would get you something like this with contracts for their respective chains (the pseudo code above includes the platform mapping table):

{
    "id": "dai",
    "symbol": "dai",
    "name": "Dai",
    "platforms": {
        "ethereum": "0x6b175474e89094c44da98b954eedeac495271d0f",
        "binance-smart-chain": "0x1af3f329e8be154074d8769d1ffa4ee058b1dbc3",
        "polygon-pos": "0x8f3cf7ad23cd3cadbd9735aff958023239c6a063"
    }
}

The contracts are sometimes empty strings (refer to pseduo code above):

{
    "id": "gooddollar",
    "symbol": "$G",
    "name": "GoodDollar",
    "platforms": {
        "ethereum": ""
    }
}

Sometimes the platforms dictionary is empty too:

 {
    "id": "01coin",
    "symbol": "zoc",
    "name": "01coin",
    "platforms": {}
}

Use this to build the token in Realm to CoinGecko token ID mapping.

(B) Pass in the list of token IDs from the mapping table built from calling (A). Note that this paginates. On iOS, we just page through until there are no results

On iOS, we call (A) and (B) once only no matter which/how many chains are enabled. Cache (A), call (B) again for fresh data.

(C) Call this for all the periods (1, 7, etc) only when the token screen needs to be displayed. Currently caching the data for days=1 for a 1 hour and caching the rest (7, 30, etc) until app restarts. Might tweak it when we build the UI.

JamesSmartCell commented 3 years ago

Thanks :), include_platform=true is the key add-on I needed, once you add that then you get all the token addresses. The platform listing is quite useful.

I was considering a similar caching pattern, will only load it when user click on the token.

hboon commented 3 years ago

Updated mapping for platforms at https://github.com/AlphaWallet/alpha-wallet-ios/blob/02a2541c41b705b79c5c8b889de9f1a91bf9a9f3/AlphaWallet/Core/CoinTicker/CoinTickersFetcher.swift#L318

Notably, Fantom is supported and there was a typo in "avalanche" earlier (it was uppercase).

hboon commented 3 years ago

Presumably already WIP for other Samoa issues like #1770. Closing for now.