Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Store bridged token price in the DB #3667

Merged
merged 2 commits into from
Mar 1, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Store bridged token price in the DB
  • Loading branch information
vbaranov committed Feb 26, 2021
commit 19ba01a5dbcdae98e3d75ea9ba9b9dfbb01311ec
6 changes: 4 additions & 2 deletions apps/explorer/lib/explorer/chain/bridged_token.ex
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ defmodule Explorer.Chain.BridgedToken do
home_token_contract_address: %Ecto.Association.NotLoaded{} | Address.t(),
home_token_contract_address_hash: Hash.Address.t(),
custom_metadata: String.t(),
type: String.t()
type: String.t(),
exchange_rate: Decimal.t()
}

@derive {Poison.Encoder,
Expand All @@ -49,6 +50,7 @@ defmodule Explorer.Chain.BridgedToken do
field(:foreign_token_contract_address_hash, Hash.Address)
field(:custom_metadata, :string)
field(:type, :string)
field(:exchange_rate, :decimal)

belongs_to(
:home_token_contract_address,
Expand All @@ -63,7 +65,7 @@ defmodule Explorer.Chain.BridgedToken do
end

@required_attrs ~w(home_token_contract_address_hash)a
@optional_attrs ~w(foreign_chain_id foreign_token_contract_address_hash custom_metadata type)a
@optional_attrs ~w(foreign_chain_id foreign_token_contract_address_hash custom_metadata type exchange_rate)a

@doc false
def changeset(%BridgedToken{} = bridged_token, params \\ %{}) do
Expand Down
52 changes: 48 additions & 4 deletions apps/explorer/lib/explorer/chain/cache/token_exchange_rate.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@ defmodule Explorer.Chain.Cache.TokenExchangeRate do
"""
use GenServer

import Ecto.Query, only: [from: 2]

alias Ecto.Changeset
alias Explorer.Chain.BridgedToken
alias Explorer.ExchangeRates.Source
alias Explorer.Repo

@cache_name :token_exchange_rate
@last_update_key "last_update"
Expand Down Expand Up @@ -50,14 +55,20 @@ defmodule Explorer.Chain.Cache.TokenExchangeRate do
"token_symbol_exchange_rate_#{symbol}"
end

def fetch(symbol) do
def fetch(token_hash, symbol) do
if cache_expired?(symbol) || value_is_empty?(symbol) do
Task.start_link(fn ->
update_cache(symbol)
update_cache(token_hash, symbol)
end)
end

fetch_from_cache(cache_key(symbol))
cached_value = fetch_from_cache(cache_key(symbol))

if is_nil(cached_value) || Decimal.cmp(cached_value, 0) == :eq do
fetch_from_db(token_hash)
else
cached_value
end
end

def cache_name, do: @cache_name
Expand All @@ -78,11 +89,12 @@ defmodule Explorer.Chain.Cache.TokenExchangeRate do
is_nil(value) || value == 0
end

defp update_cache(symbol) do
defp update_cache(token_hash, symbol) do
put_into_cache("#{cache_key(symbol)}_#{@last_update_key}", current_time())

exchange_rate = fetch_token_exchange_rate(symbol)

put_into_db(token_hash, exchange_rate)
put_into_cache(cache_key(symbol), exchange_rate)
end

Expand All @@ -106,12 +118,44 @@ defmodule Explorer.Chain.Cache.TokenExchangeRate do
end
end

defp fetch_from_db(nil), do: nil

defp fetch_from_db(token_hash) do
token = get_token(token_hash)

if token do
token.exchange_rate
else
nil
end
end

def put_into_cache(key, value) do
if cache_table_exists?() do
:ets.insert(@cache_name, {key, value})
end
end

def put_into_db(token_hash, exchange_rate) do
token = get_token(token_hash)

if token do
token
|> Changeset.change(%{exchange_rate: exchange_rate})
|> Repo.update()
end
end

defp get_token(token_hash) do
query =
from(bt in BridgedToken,
where: bt.home_token_contract_address_hash == ^token_hash
)

query
|> Repo.one()
end

defp current_time do
utc_now = DateTime.utc_now()

Expand Down
9 changes: 5 additions & 4 deletions apps/explorer/lib/explorer/chain/supply/token_bridge.ex
Original file line number Diff line number Diff line change
Expand Up @@ -194,12 +194,13 @@ defmodule Explorer.Chain.Supply.TokenBridge do
omni_bridge_market_cap
end

def get_current_price_for_bridged_token(symbol) when is_nil(symbol), do: nil
def get_current_price_for_bridged_token(_token_hash, symbol) when is_nil(symbol), do: nil
def get_current_price_for_bridged_token(token_hash, _symbol) when is_nil(token_hash), do: nil

def get_current_price_for_bridged_token(symbol) do
def get_current_price_for_bridged_token(token_hash, symbol) do
bridged_token_symbol_for_price_fetching = bridged_token_symbol_mapping_to_get_price(symbol)

TokenExchangeRateCache.fetch(bridged_token_symbol_for_price_fetching)
TokenExchangeRateCache.fetch(token_hash, bridged_token_symbol_for_price_fetching)
end

def get_bridged_mainnet_tokens_list do
Expand All @@ -221,7 +222,7 @@ defmodule Explorer.Chain.Supply.TokenBridge do
bridged_mainnet_tokens_with_supply =
bridged_mainnet_tokens_list
|> Enum.map(fn {bridged_token_hash, bridged_token_symbol} ->
bridged_token_price_from_cache = TokenExchangeRateCache.fetch(bridged_token_symbol)
bridged_token_price_from_cache = TokenExchangeRateCache.fetch(bridged_token_hash, bridged_token_symbol)

bridged_token_price =
if bridged_token_price_from_cache && Decimal.cmp(bridged_token_price_from_cache, 0) == :gt do
Expand Down
4 changes: 2 additions & 2 deletions apps/explorer/lib/explorer/counters/bridge.ex
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,8 @@ defmodule Explorer.Counters.Bridge do
bridged_mainnet_tokens_list = TokenBridge.get_bridged_mainnet_tokens_list()

bridged_mainnet_tokens_list
|> Enum.each(fn {_bridged_token_hash, bridged_token_symbol} ->
bridged_token_price = TokenBridge.get_current_price_for_bridged_token(bridged_token_symbol)
|> Enum.each(fn {bridged_token_hash, bridged_token_symbol} ->
bridged_token_price = TokenBridge.get_current_price_for_bridged_token(bridged_token_hash, bridged_token_symbol)
cache_key = TokenExchangeRate.cache_key(bridged_token_symbol)
TokenExchangeRate.put_into_cache(cache_key, bridged_token_price)
end)
Expand Down
2 changes: 1 addition & 1 deletion apps/explorer/lib/explorer/market/market.ex
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ defmodule Explorer.Market do
fetch_token_usd_value(matches_known_address, symbol)

mainnet_bridged_token?(token) ->
TokenBridge.get_current_price_for_bridged_token(symbol)
TokenBridge.get_current_price_for_bridged_token(token.contract_address_hash, symbol)

true ->
nil
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
defmodule Explorer.Repo.Migrations.AddExchangeRateColumnToBridgedTokens do
use Ecto.Migration

def change do
alter table("bridged_tokens") do
add(:exchange_rate, :decimal)
end
end
end