Skip to content

Commit

Permalink
Merge pull request #2094 from nervosnetwork/develop
Browse files Browse the repository at this point in the history
Deploy to testnet
  • Loading branch information
rabbitz committed Jul 24, 2024
2 parents aa2bf15 + 195242b commit a4c11c0
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 38 deletions.
2 changes: 1 addition & 1 deletion app/controllers/api/v1/xudts_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def download_csv
end

def snapshot
args = params.permit(:id, :number)
args = params.permit(:id, :number, :merge_with_owner)
file = CsvExportable::ExportUdtSnapshotJob.perform_now(args.to_h)

if params[:format] == "json"
Expand Down
1 change: 1 addition & 0 deletions app/controllers/api/v2/bitcoin_vouts_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ def verify
bitcoin_vouts: { index: previous_vout["index"], op_return: false })
bitcoin_vouts.each do |vout|
next if vout.unbound? || vout.normal?
next unless vout.cell_output

status =
if vout.cell_output.dead?
Expand Down
4 changes: 2 additions & 2 deletions app/jobs/csv_exportable/base_exporter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,11 @@ def parse_udt_amount(amount, decimal)
result = amount_big_decimal / (BigDecimal(10)**decimal_int)

if decimal_int > 20
return "#{result.round(20).to_s('F')}..."
return "#{format('%.2f', result.round(20))}..."
end

if result.to_s.length >= 16 || result < BigDecimal("0.000001")
return result.round(decimal_int).to_s("F")
return format("%.#{decimal_int}f", result.round(decimal_int))
end

result.to_s("F")
Expand Down
88 changes: 53 additions & 35 deletions app/jobs/csv_exportable/export_udt_snapshot_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,68 +3,86 @@ class ExportUdtSnapshotJob < BaseExporter
attr_accessor :udt, :block

def perform(args)
find_block_and_udt(args)
type_script = TypeScript.find_by(@udt.type_script)

cell_outputs = fetch_cell_outputs(type_script.id)
data = fetch_address_data(cell_outputs)
merged_data = merge_data(data, to_boolean(args[:merge_with_owner]))

header = generate_header(to_boolean(args[:merge_with_owner]))
rows = prepare_rows(merged_data)

generate_csv(header, rows)
end

private

def find_block_and_udt(args)
@block = Block.find_by!(number: args[:number])
@udt = Udt.published_xudt.find_by!(type_hash: args[:id])
type_script = TypeScript.find_by(@udt.type_script)
end

def fetch_cell_outputs(type_script_id)
condition = <<-SQL
type_script_id = #{type_script.id} AND
type_script_id = #{type_script_id} AND
block_timestamp <= #{@block.timestamp} AND
(consumed_block_timestamp > #{@block.timestamp} OR consumed_block_timestamp IS NULL)
SQL
cell_outputs = CellOutput.where(condition).group(:address_id).sum(:udt_amount)
cell_outputs = cell_outputs.reject { |_, v| v.to_f.zero? }
cell_outputs.reject { |_, v| v.to_f.zero? }
end

data = []
cell_outputs.keys.each_slice(1000) do |address_ids|
def fetch_address_data(cell_outputs)
cell_outputs.keys.each_slice(1000).flat_map do |address_ids|
addresses = Address.includes(bitcoin_address_mapping: [:bitcoin_address]).
where(id: address_ids).pluck("addresses.id", "addresses.address_hash", "bitcoin_addresses.address_hash")

addresses.each do |address|
data << {
addresses.map do |address|
{
address_hash: address[1],
bitcoin_address_hash: address[2],
udt_amount: cell_outputs[address[0]],
}
end
end
end

rows = []
data.sort_by { |item| -item[:udt_amount] }.each do |item|
row = generate_row(item)
next if row.blank?

rows << row
def merge_data(data, merge_with_owner)
data.each_with_object(Hash.new(0)) do |entry, hash|
owner = merge_with_owner ? (entry[:bitcoin_address_hash].presence || entry[:address_hash]) : entry[:address_hash]
hash[owner] += entry[:udt_amount]
end
end

header = ["Token Symbol", "Block Height", "UnixTimestamp", "date(UTC)", "Owner", "CKB Address", "Amount"]
generate_csv(header, rows)
def prepare_rows(merged_data)
merged_data.sort_by { |_, amount| -amount }.map { |item| generate_row(item) }.compact
end

def generate_row(item)
datetime = datetime_utc(@block.timestamp)
decimal = @udt.decimal

if (decimal = @udt.decimal)
[
@udt.symbol,
@block.number,
@block.timestamp,
datetime,
item[:bitcoin_address_hash] || item[:address_hash],
item[:address_hash],
parse_udt_amount(item[:udt_amount].to_d, decimal),
]
[
@udt.symbol,
@block.number,
@block.timestamp,
datetime,
item[0],
decimal.present? ? parse_udt_amount(item[1].to_d, decimal) : "#{item[1]} (raw)",
]
end

def generate_header(merge_with_owner)
if merge_with_owner
["Token Symbol", "Block Height", "UnixTimestamp", "date(UTC)", "Owner", "Amount"]
else
[
@udt.symbol,
@block.number,
@block.timestamp,
datetime,
item[:bitcoin_address_hash] || item[:address_hash],
item[:address_hash],
"#{item[:udt_amount]} (raw)",
]
["Token Symbol", "Block Height", "UnixTimestamp", "date(UTC)", "CKB Address", "Amount"]
end
end

def to_boolean(param)
param == true || param.to_s.downcase == "true" || param.to_s == "1"
end
end
end
end

0 comments on commit a4c11c0

Please sign in to comment.