From 0fbdb0d3eca1d40e065a3fa5f8d22d1d7c35872d Mon Sep 17 00:00:00 2001 From: Rabbit Date: Mon, 19 Feb 2024 16:34:59 +0800 Subject: [PATCH] fix: adjust the count of nft cells change (#1625) --- .../concerns/cell_data_comparator.rb | 94 +++++++++++++------ 1 file changed, 64 insertions(+), 30 deletions(-) diff --git a/app/controllers/concerns/cell_data_comparator.rb b/app/controllers/concerns/cell_data_comparator.rb index 860840d32..3f259d8f7 100644 --- a/app/controllers/concerns/cell_data_comparator.rb +++ b/app/controllers/concerns/cell_data_comparator.rb @@ -10,10 +10,10 @@ def compare_cells(transaction) udt_transfers = diff_udt_cells(inputs, outputs) cota_nft_transfers = diff_cota_nft_cells(transaction, inputs, outputs) normal_nft_transfers = diff_normal_nft_cells(inputs, outputs) - nft_class_transfers = diff_nft_capacities(inputs, outputs) + dao_transfers = diff_dao_capacities(inputs, outputs) merged_transfers = - [normal_transfers, udt_transfers, cota_nft_transfers, normal_nft_transfers, nft_class_transfers].reduce do |acc, h| + [normal_transfers, udt_transfers, cota_nft_transfers, normal_nft_transfers, dao_transfers].reduce do |acc, h| acc.merge(h) { |_, ov, nv| ov + nv } end @@ -73,6 +73,20 @@ def diff_udt_cells(inputs, outputs) transfers end + def diff_dao_capacities(inputs, outputs) + transfers = Hash.new { |h, k| h[k] = Array.new } + cell_types = %w(nervos_dao_deposit nervos_dao_withdrawing) + inputs = inputs.where(cell_type: cell_types).group(:address_id, :cell_type).sum(:capacity) + outputs = outputs.where(cell_type: cell_types).group(:address_id, :cell_type).sum(:capacity) + + (inputs.keys | outputs.keys).each do |k| + capacity = outputs[k].to_f - inputs[k].to_f + transfers[k[0]] << CkbUtils.hash_value_to_s({ capacity:, cell_type: k[1] }) + end + + transfers + end + def diff_cota_nft_cells(transaction, inputs, outputs) transfers = Hash.new { |h, k| h[k] = Array.new } inputs = inputs.cota_regular.group(:address_id).sum(:capacity) @@ -88,58 +102,78 @@ def diff_cota_nft_cells(transaction, inputs, outputs) def diff_normal_nft_cells(inputs, outputs) transfers = Hash.new { |h, k| h[k] = Array.new } - cell_types = %w(m_nft_token nrc_721_token spore_cell) + nft_infos = Hash.new { |h, k| h[k] = nil } + cell_types = %w(m_nft_token nrc_721_token spore_cell m_nft_issuer m_nft_class nrc_721_factory cota_registry spore_cluster) - process_nft = ->(c, h) { + process_nft = ->(c, h, o) { k = [c.address_id, c.cell_type, c.type_hash] h[k] ||= { capacity: 0.0, count: 0 } h[k][:capacity] += c.capacity - h[k][:count] -= 1 + h[k][:count] += o + + unless nft_infos[c.type_hash] + nft_infos[c.type_hash] = nft_info(c) + end } - inputs = inputs.where(cell_type: cell_types).each_with_object({}) { |c, h| process_nft.call(c, h) } - outputs = outputs.where(cell_type: cell_types).each_with_object({}) { |c, h| process_nft.call(c, h) } + inputs = inputs.where(cell_type: cell_types).each_with_object({}) { |c, h| process_nft.call(c, h, -1) } + outputs = outputs.where(cell_type: cell_types).each_with_object({}) { |c, h| process_nft.call(c, h, 1) } (inputs.keys | outputs.keys).each do |k| address_id, cell_type, type_hash = k - token_id, collection_name = token_info(type_hash) input = inputs[k] output = outputs[k] capacity = output&.dig(:capacity).to_f - input&.dig(:capacity).to_f count = output&.dig(:count).to_i + input&.dig(:count).to_i - transfers[address_id] << CkbUtils.hash_value_to_s({ capacity:, cell_type:, token_id:, collection_name:, count: }) + transfer = { capacity:, cell_type:, count: } + transfer.merge!(nft_infos[type_hash]) if nft_infos[type_hash] + transfers[address_id] << CkbUtils.hash_value_to_s(transfer) end transfers end - def diff_nft_capacities(inputs, outputs) - transfers = Hash.new { |h, k| h[k] = Array.new } - cell_types = %w(m_nft_issuer m_nft_class nrc_721_factory cota_registry spore_cluster) - inputs = inputs.where(cell_type: cell_types).group(:address_id, :cell_type).sum(:capacity) - outputs = outputs.where(cell_type: cell_types).group(:address_id, :cell_type).sum(:capacity) - - (inputs.keys | outputs.keys).each do |k| - capacity = outputs[k].to_f - inputs[k].to_f - transfers[k[0]] << CkbUtils.hash_value_to_s({ capacity:, cell_type: k[1] }) + def nft_info(cell) + case cell.cell_type + when "m_nft_token", "nrc_721_token", "spore_cell" + item = TokenItem.joins(:type_script).where(type_script: { script_hash: cell.type_hash }).take + { toekn_id: item&.token_id, name: item&.collection&.name } + when "m_nft_issuer" + { name: CkbUtils.parse_issuer_data(cell.data).info["name"] } + when "m_nft_class" + { name: CkbUtils.parse_token_class_data(cell.data).name } + when "nrc_721_factory" + type_script = cell.type_script + factory_cell = NrcFactoryCell.find_by( + code_hash: type_script.code_hash, + hash_type: type_script.hash_type, + args: type_script.args, + verified: true, + ) + { name: factory_cell&.name } + when "spore_cluster" + { name: CkbUtils.parse_spore_cluster_data(cell.data)[:name] } + when "omiga_inscription_info" + type_script = cell.type_script + info = OmigaInscriptionInfo.find_by( + code_hash: type_script.code_hash, + hash_type: type_script.hash_type, + args: type_script.args, + ) + { name: info&.name } end - - transfers - end - - def token_info(script_hash) - item = TokenItem.joins(:type_script).where(type_script: { script_hash: }).take - [item&.token_id, item&.collection&.name] end def cota_info(transaction, address_id) info = Array.new process_transfer = ->(item, count) { collection = item.collection - info << CkbUtils.hash_value_to_s({ - collection_name: collection.name, - count:, - token_id: item.token_id, - }) + info << CkbUtils.hash_value_to_s( + { + name: collection.name, + count:, + token_id: item.token_id, + }, + ) } transaction.token_transfers.each do |t|