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

Hotfix balance #2364

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
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
6 changes: 3 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ jobs:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: satackey/[email protected]
# Ignore the failure of a step and avoid terminating the job.
continue-on-error: true
# - uses: satackey/[email protected]
# # Ignore the failure of a step and avoid terminating the job.
# continue-on-error: true
- name: Build and push
id: docker_build
uses: mr-smithers-excellent/docker-build-push@v5
Expand Down
24 changes: 24 additions & 0 deletions app/controllers/api/v2/rgbpp_assets_statistics_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
module Api
module V2
class RgbppAssetsStatisticsController < BaseController
def index
expires_in 15.minutes, public: true, stale_while_revalidate: 5.minutes, stale_if_error: 5.minutes

statistics = RgbppAssetsStatistic.all.order(created_at_unixtimestamp: :asc)
statistics = statistics.where(network: params[:network]) if params[:network].present?
statistics = statistics.where(indicator: params[:indicators].split(",")) if params[:indicators].present?

render json: {
data: statistics.map do |statistic|
{
indicator: statistic.indicator,
value: statistic.value.to_s,
network: statistic.network,
created_at_unixtimestamp: statistic.created_at_unixtimestamp.to_s,
}
end,
}
end
end
end
end
28 changes: 28 additions & 0 deletions app/controllers/api/v2/udt_hourly_statistics_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
module Api
module V2
class UdtHourlyStatisticsController < BaseController
def show
expires_in 15.minutes, public: true, stale_while_revalidate: 5.minutes, stale_if_error: 5.minutes

udt = Udt.find_by!(type_hash: params[:id], published: true)
hourly_statistics =
if udt.present?
UdtHourlyStatistic.where(udt:).order(created_at_unixtimestamp: :asc)
else
UdtHourlyStatistic.none
end

render json: {
data: hourly_statistics.map do |statistic|
{
ckb_transactions_count: statistic.ckb_transactions_count.to_s,
amount: statistic.amount.to_s,
holders_count: statistic.holders_count.to_s,
created_at_unixtimestamp: statistic.created_at_unixtimestamp.to_s,
}
end,
}
end
end
end
end
4 changes: 2 additions & 2 deletions app/models/address.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ class Address < ApplicationRecord
has_one :bitcoin_address_mapping, foreign_key: "ckb_address_id"
has_one :bitcoin_address, through: :bitcoin_address_mapping

validates :balance, :cell_consumed, :ckb_transactions_count, :interest, :dao_deposit,
numericality: { greater_than_or_equal_to: 0 }, allow_nil: true
# validates :balance, :cell_consumed, :ckb_transactions_count, :interest, :dao_deposit,
# numericality: { greater_than_or_equal_to: 0 }, allow_nil: true
validates :lock_hash, presence: true, uniqueness: true

scope :visible, -> { where(visible: true) }
Expand Down
6 changes: 4 additions & 2 deletions app/models/cell_dependency.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ def to_raw
# Table name: cell_dependencies
#
# id :bigint not null, primary key
# contract_id :bigint
# ckb_transaction_id :bigint not null
# dep_type :integer
# contract_cell_id :bigint not null
# script_id :bigint
# contract_id :bigint
# implicit :boolean
# implicit :boolean default(TRUE), not null
# block_number :bigint
# tx_index :integer
# contract_analyzed :boolean default(FALSE)
Expand All @@ -40,6 +40,8 @@ def to_raw
#
# index_cell_dependencies_on_block_number_and_tx_index (block_number,tx_index)
# index_cell_dependencies_on_contract_analyzed (contract_analyzed)
# index_cell_dependencies_on_contract_id (contract_id)
# index_cell_dependencies_on_script_id (script_id)
# index_cell_dependencies_on_tx_id_and_cell_id_and_dep_type (ckb_transaction_id,contract_cell_id,dep_type) UNIQUE
# index_on_cell_dependencies_contract_cell_block_tx (contract_cell_id,block_number DESC,tx_index DESC)
#
2 changes: 1 addition & 1 deletion app/models/ckb_sync/api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ def xudt_data_hash
end

def xudt_compatible_code_hashes
[Settings.xudt_compatible_code_hash, Settings.xudt_compatible2_code_hash, Settings.xudt_compatible3_code_hash]
[Settings.xudt_compatible_code_hash, Settings.xudt_compatible2_code_hash, Settings.xudt_compatible3_code_hash, Settings.xudt_compatible4_code_hash]
end

def unique_cell_code_hash
Expand Down
21 changes: 21 additions & 0 deletions app/models/rgbpp_assets_statistic.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
class RgbppAssetsStatistic < ApplicationRecord
enum :network, %i[global ckb btc]
enum :indicator, %i[ft_count dob_count holders_count transactions_count]
end

# == Schema Information
#
# Table name: rgbpp_assets_statistics
#
# id :bigint not null, primary key
# indicator :integer not null
# value :decimal(40, ) default(0)
# network :integer default("global")
# created_at_unixtimestamp :integer
# created_at :datetime not null
# updated_at :datetime not null
#
# Indexes
#
# index_on_indicator_and_network_and_created_at_unixtimestamp (indicator,network,created_at_unixtimestamp) UNIQUE
#
18 changes: 18 additions & 0 deletions app/models/rgbpp_hourly_statistic.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
class RgbppHourlyStatistic < ApplicationRecord
end

# == Schema Information
#
# Table name: rgbpp_hourly_statistics
#
# id :bigint not null, primary key
# xudt_count :integer default(0)
# dob_count :integer default(0)
# created_at_unixtimestamp :integer
# created_at :datetime not null
# updated_at :datetime not null
#
# Indexes
#
# index_rgbpp_hourly_statistics_on_created_at_unixtimestamp (created_at_unixtimestamp) UNIQUE
#
40 changes: 40 additions & 0 deletions app/models/udt_hourly_statistic.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
class UdtHourlyStatistic < ApplicationRecord
belongs_to :udt

def percentage_change(attribute)
yesterday = previous_stat(udt_id, 1)
day_before_yesterday = previous_stat(udt_id, 2)

return nil unless yesterday && day_before_yesterday

yesterday_value = yesterday.public_send(attribute)
day_before_yesterday_value = day_before_yesterday.public_send(attribute)

return nil if day_before_yesterday_value.zero?

((yesterday_value - day_before_yesterday_value).to_f / day_before_yesterday_value * 100).round(2)
end

def previous_stat(udt_id, days_ago)
timestamp = (Time.current - days_ago.days).beginning_of_day.to_i
self.class.find_by(udt_id:, created_at_unixtimestamp: timestamp)
end
end

# == Schema Information
#
# Table name: udt_hourly_statistics
#
# id :bigint not null, primary key
# udt_id :bigint not null
# ckb_transactions_count :integer default(0)
# amount :decimal(40, ) default(0)
# holders_count :integer default(0)
# created_at_unixtimestamp :integer
# created_at :datetime not null
# updated_at :datetime not null
#
# Indexes
#
# index_on_udt_id_and_unixtimestamp (udt_id,created_at_unixtimestamp) UNIQUE
#
2 changes: 1 addition & 1 deletion app/views/api/v2/fiber/graph_nodes/show.jbuilder
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ json.data do
json.udt_cfg_infos @node.udt_cfg_infos

json.fiber_graph_channels @graph_channels do |channel|
json.(channel, :channel_outpoint, :node1, :node2, :chain_hash, :open_transaction_info, :closed_transaction_info)
json.(channel, :channel_outpoint, :node1, :node2, :chain_hash, :open_transaction_info, :closed_transaction_info, :udt_info)
json.funding_tx_block_number channel.funding_tx_block_number.to_s
json.funding_tx_index channel.funding_tx_index.to_s
json.last_updated_timestamp channel.last_updated_timestamp.to_s
Expand Down
12 changes: 11 additions & 1 deletion app/workers/fiber_graph_detect_worker.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,18 @@ class FiberGraphDetectWorker
include Sidekiq::Worker
sidekiq_options queue: "fiber"

attr_accessor :graph_node_ids, :graph_channel_outpoint

def perform
@graph_node_ids = []
@graph_channel_outpoints = []

# sync graph nodes and channels
["nodes", "channels"].each { fetch_graph_infos(_1) }
# purge outdated graph nodes
FiberGraphNode.where.not(node_id: @graph_node_ids).destroy_all
# purge outdated graph channels
FiberGraphChannel.where.not(channel_outpoint: @graph_channel_outpoints).destroy_all

# check channel is closed
FiberGraphChannel.open_channels.each do |channel|
Expand Down Expand Up @@ -61,7 +70,7 @@ def upsert_node_with_cfg_info(node)
peer_id: extract_peer_id(node["addresses"]),
auto_accept_min_ckb_funding_amount: node["auto_accept_min_ckb_funding_amount"],
}

@graph_node_ids << node_attributes[:node_id]
fiber_graph_node = FiberGraphNode.upsert(node_attributes, unique_by: %i[node_id], returning: %i[id])

return unless fiber_graph_node && node["udt_cfg_infos"].present?
Expand All @@ -87,6 +96,7 @@ def build_channel_attributes(channel)

channel_outpoint = channel["channel_outpoint"]
open_transaction = CkbTransaction.find_by(tx_hash: channel_outpoint[0..65])
@graph_channel_outpoints << channel_outpoint

{
channel_outpoint:,
Expand Down
88 changes: 88 additions & 0 deletions app/workers/generate_rgbpp_assets_statistic_worker.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
class GenerateRgbppAssetsStatisticWorker
include Sidekiq::Job
sidekiq_options queue: "rgbpp"

attr_accessor :datetime

def perform(datetime = nil)
@datetime = datetime
statistic_attributes = [
ft_count_attributes,
dob_count_attributes,
btc_transactions_count_attributes,
ckb_transactions_count_attributes,
btc_holders_count_attributes,
ckb_holders_count_attributes,
]
statistic_attributes.each { _1[:created_at_unixtimestamp] = started_at.to_i }
RgbppAssetsStatistic.upsert_all(statistic_attributes, unique_by: %i[indicator network created_at_unixtimestamp])
rescue StandardError => e
Rails.logger.error "Error occurred during GenerateRgbppHourlyStatistic error: #{e.message}"
end

private

def ft_count_attributes
timestamp = CkbUtils.time_in_milliseconds(ended_at) - 1
xudts_count = Udt.published_xudt.where(block_timestamp: ..timestamp).count
{ indicator: "ft_count", value: xudts_count, network: "global" }
end

def dob_count_attributes
timestamp = CkbUtils.time_in_milliseconds(ended_at) - 1
token_collections_count = TokenCollection.where("tags && ARRAY[?]::varchar[]", ["rgb++"]).
where(block_timestamp: ..timestamp).count
{ indicator: "dob_count", value: token_collections_count, network: "global" }
end

def btc_transactions_count_attributes
transactions_count = BitcoinTransaction.where(time: started_at.to_i..ended_at.to_i).count
{ indicator: "transactions_count", value: transactions_count, network: "btc" }
end

def ckb_transactions_count_attributes
started_timestamp = CkbUtils.time_in_milliseconds(started_at)
ended_timestamp = CkbUtils.time_in_milliseconds(ended_at) - 1
transactions_count = BitcoinAnnotation.includes(:ckb_transaction).
where(ckb_transactions: { block_timestamp: started_timestamp..ended_timestamp }).count
{ indicator: "transactions_count", value: transactions_count, network: "ckb" }
end

def btc_holders_count_attributes
udt_types = %i[xudt xudt_compatible spore_cell did_cell]
udt_ids = Udt.where(udt_type: udt_types, published: true).ids
address_ids = UdtAccount.where(udt_id: udt_ids).where("amount > 0").pluck(:address_id).uniq
holders_count = BitcoinAddressMapping.where(ckb_address_id: address_ids, created_at: ..ended_at).
distinct.count(:bitcoin_address_id)
{ indicator: "holders_count", value: holders_count, network: "btc" }
end

def ckb_holders_count_attributes
udt_types = %i[xudt xudt_compatible spore_cell did_cell]
udt_ids = Udt.where(udt_type: udt_types, published: true).ids
holders_count = UdtAccount.where(udt_id: udt_ids, created_at: ..ended_at).
where("amount > 0").distinct.count(:address_id)
{ indicator: "holders_count", value: holders_count, network: "ckb" }
end

def to_be_counted_date
if @datetime.present?
return Time.zone.parse(@datetime)
end

last_record = UdtHourlyStatistic.order(created_at_unixtimestamp: :desc).first
if last_record
Time.zone.at(last_record.created_at_unixtimestamp) + 1.day
else
Time.current.yesterday
end
end

def started_at
@started_at ||= to_be_counted_date.beginning_of_day
end

def ended_at
@ended_at ||= to_be_counted_date.end_of_day
end
end
61 changes: 61 additions & 0 deletions app/workers/generate_udt_hourly_statistic_worker.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
class GenerateUdtHourlyStatisticWorker
include Sidekiq::Job

def perform(datetime = nil)
ActiveRecord::Base.connection.execute("SET statement_timeout = 0")
start_time = to_be_counted_date(datetime)
generate_statistics(start_time)
ActiveRecord::Base.connection.execute("RESET statement_timeout")
rescue StandardError => e
Rails.logger.error "Error occurred during GenerateUdtHourlyStatistic error: #{e.message}"
end

private

def to_be_counted_date(datetime)
last_record = UdtHourlyStatistic.order(created_at_unixtimestamp: :desc).first
if last_record
Time.zone.at(last_record.created_at_unixtimestamp) + 1.day
else
datetime.is_a?(String) ? Time.zone.parse(datetime) : Time.current.yesterday
end
end

def generate_statistics(start_time)
puts "Generating udt hourly statistics for #{start_time}"
statistic_attributes = []
udt_types = %i[xudt xudt_compatible spore_cell did_cell]
Udt.where(udt_type: udt_types, published: true).find_each do |udt|
statistic_attributes << {
udt_id: udt.id,
amount: calc_amount(udt),
ckb_transactions_count: calc_ckb_transactions_count(udt),
holders_count: calc_holders_count(udt),
created_at_unixtimestamp: start_time.beginning_of_day.to_i,
}
end

if statistic_attributes.present?
UdtHourlyStatistic.upsert_all(statistic_attributes, unique_by: %i[udt_id created_at_unixtimestamp])
end
end

def calc_amount(udt)
inputs_amount = 0
outputs_amount = 0
udt.ckb_transactions.includes(:cell_outputs).find_in_batches(batch_size: 1000) do |transactions|
ids = transactions.map(&:id)
inputs_amount += CellOutput.select(:udt_amount).where(consumed_by_id: ids).sum(:udt_amount)
outputs_amount += CellOutput.select(:udt_amount).where(ckb_transaction_id: ids).sum(:udt_amount)
end
[inputs_amount, outputs_amount].max
end

def calc_ckb_transactions_count(udt)
udt.ckb_transactions.count
end

def calc_holders_count(udt)
udt.udt_holder_allocations.sum("ckb_holder_count + btc_holder_count")
end
end
2 changes: 2 additions & 0 deletions config/routes/v2.rb
Original file line number Diff line number Diff line change
Expand Up @@ -106,5 +106,7 @@
resources :graph_nodes, param: :node_id, only: %i[index show]
resources :graph_channels, only: :index
end
resources :udt_hourly_statistics, only: :show
resources :rgbpp_assets_statistics, only: :index
end
end
Loading
Loading