forked from coingecko/cryptoexchange
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request coingecko#2118 from coingecko/curve
Add support for Curve finance
- Loading branch information
Showing
10 changed files
with
408 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
module Cryptoexchange::Exchanges | ||
module Curve | ||
class Authentication < Cryptoexchange::Services::Authentication | ||
def api_key | ||
HashHelper.dig(Cryptoexchange::Credentials.get(@exchange), 'api_key') | ||
end | ||
|
||
def headers | ||
# Do nothing, no headers override needed for API key only | ||
end | ||
|
||
def required_credentials | ||
%i(api_key) | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
module Cryptoexchange::Exchanges | ||
module Curve | ||
class Market < Cryptoexchange::Models::Market | ||
NAME = 'curve' | ||
|
||
def self.api_key | ||
authentication = Cryptoexchange::Exchanges::Curve::Authentication.new( | ||
:market, | ||
Cryptoexchange::Exchanges::Curve::Market::NAME | ||
) | ||
authentication.validate_credentials! | ||
authentication.api_key | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
module Cryptoexchange::Exchanges | ||
module Curve | ||
module Services | ||
class Market < Cryptoexchange::Services::Market | ||
class << self | ||
def supports_individual_ticker_query? | ||
true | ||
end | ||
end | ||
|
||
HOURS_24 = 24*60*60 | ||
|
||
def fetch(market_pair) | ||
tokens_response = TheGraphClient::Client.query(TheGraphClient::TokensQuery) | ||
tokens = tokens_response.data.tokens | ||
|
||
# Get the token information | ||
# Decimals to calculate price, Id to pass into graphql | ||
base_token = tokens.select { |token| token.symbol == market_pair.base_raw }.first | ||
base_token_id = base_token.id | ||
base_token_decimals = base_token.decimals.to_i | ||
target_token = tokens.select { |token| token.symbol == market_pair.target_raw }.first | ||
target_token_id = target_token.id | ||
target_token_decimals = target_token.decimals.to_i | ||
|
||
# Get swaps from both direction | ||
# Example, DAI-ETH and ETH-DAI | ||
swaps_response = TheGraphClient::Client.query(TheGraphClient::SwapsQuery, variables: { fromToken: base_token_id, toToken: target_token_id, range_timestamp: Time.now.to_i - HOURS_24 }) | ||
swaps_response_inverse = TheGraphClient::Client.query(TheGraphClient::SwapsQuery, variables: { fromToken: target_token_id, toToken: base_token_id, range_timestamp: Time.now.to_i - HOURS_24 }) | ||
latest_swap = swaps_response.data.swaps.first | ||
latest_swap_inverse = swaps_response_inverse.data.swaps.first | ||
|
||
# Put the latest swap from both side together so we can compare and get the latest of the two | ||
latest_swaps = [] | ||
latest_swaps << latest_swap if latest_swap | ||
latest_swaps << latest_swap_inverse if latest_swap_inverse | ||
last_swap = latest_swaps.max_by { |k| k.timestamp} | ||
|
||
if last_swap | ||
last_price = 1.0 / last_swap.underlying_price.to_f | ||
volume = swaps_response.data.swaps.map(&:from_token_amount).map { |s| s.to_f / 10**base_token_decimals }.sum | ||
volume_inverse = swaps_response_inverse.data.swaps.map(&:to_token_amount).map { |s| s.to_f / 10**base_token_decimals }.sum | ||
|
||
adapt(last_price, market_pair, volume + volume_inverse) | ||
end | ||
end | ||
|
||
def adapt(last_price, market_pair, volume) | ||
ticker = Cryptoexchange::Models::Ticker.new | ||
ticker.base = market_pair.base | ||
ticker.target = market_pair.target | ||
ticker.market = Curve::Market::NAME | ||
ticker.last = last_price.to_f | ||
ticker.volume = volume.to_f | ||
ticker.timestamp = nil | ||
ticker.payload = { last_price: last_price, volume: volume } | ||
ticker | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
module Cryptoexchange::Exchanges | ||
module Curve | ||
module Services | ||
class Pairs < Cryptoexchange::Services::Pairs | ||
def pairs_url | ||
"https://api.blocklytics.org/pools/v1/pairs?platform=Curve&key=#{Cryptoexchange::Exchanges::Curve::Market.api_key}" | ||
end | ||
|
||
def fetch | ||
output = fetch_via_api(pairs_url) | ||
adapt(output) | ||
end | ||
|
||
def adapt(output) | ||
market_pairs = [] | ||
output.each do |pair| | ||
base, target = pair["pair"].split("-") | ||
market_pairs << Cryptoexchange::Models::MarketPair.new( | ||
base: base, | ||
target: target, | ||
market: Curve::Market::NAME, | ||
) | ||
end | ||
market_pairs | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
require "graphql/client" | ||
require "graphql/client/http" | ||
|
||
module Cryptoexchange::Exchanges | ||
module Curve | ||
class TheGraphClient < Cryptoexchange::Models::Market | ||
HTTP = GraphQL::Client::HTTP.new("https://api.thegraph.com/subgraphs/name/blocklytics/curve") do | ||
end | ||
Schema = GraphQL::Client.load_schema(HTTP) | ||
Client = GraphQL::Client.new(schema: Schema, execute: HTTP) | ||
|
||
TokensQuery = Client.parse <<-'GRAPHQL' | ||
query | ||
{ | ||
tokens { | ||
id | ||
symbol | ||
decimals | ||
} | ||
} | ||
GRAPHQL | ||
|
||
SwapsQuery = Client.parse <<-'GRAPHQL' | ||
query($fromToken: String!, $toToken: String!, $range_timestamp: BigInt!) | ||
{ | ||
swaps(orderBy: timestamp, orderDirection: desc, where: { isUnderlyingSwap: false, fromToken: $fromToken, toToken: $toToken, timestamp_gte: $range_timestamp } ){ | ||
fromTokenAmount, | ||
toTokenAmount, | ||
underlyingPrice, | ||
timestamp | ||
} | ||
} | ||
GRAPHQL | ||
end | ||
end | ||
end |
44 changes: 44 additions & 0 deletions
44
spec/cassettes/vcr_cassettes/Curve/integration_specs_fetch_pairs.yml
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Oops, something went wrong.