From 161b02dccfccc8d45b65e3f4a3a04d5a11288d17 Mon Sep 17 00:00:00 2001 From: Miles Zhang Date: Tue, 9 Jan 2024 13:45:51 +0800 Subject: [PATCH 1/8] Issue 508 (#1557) * feat: parse omiga inscription info cell data Signed-off-by: Miles Zhang * feat: create omiga_inscription_info model Signed-off-by: Miles Zhang * feat: save omiga inscription info and udt in sync process Signed-off-by: Miles Zhang * feat: add omiga_inscription api Signed-off-by: Miles Zhang * test: fix test Signed-off-by: Miles Zhang --------- Signed-off-by: Miles Zhang --- .../api/v1/omiga_inscriptions_controller.rb | 67 +++++++++ app/models/cell_input.rb | 16 +- app/models/cell_output.rb | 93 +++++++----- app/models/ckb_sync/api.rb | 27 +++- .../ckb_sync/new_node_data_processor.rb | 34 ++++- app/models/omiga_inscription_info.rb | 29 ++++ app/models/udt.rb | 23 +-- app/models/udt_account.rb | 9 +- .../omiga_inscription_info_serializer.rb | 18 +++ app/serializers/udt_serializer.rb | 27 +++- app/utils/ckb_utils.rb | 138 ++++++++++++------ config/routes.rb | 12 +- config/settings.mainnet.yml | 7 + config/settings.testnet.yml | 6 + ...107100346_create_omiga_inscription_info.rb | 20 +++ db/structure.sql | 66 ++++++++- .../v1/omiga_inscriptions_controller_test.rb | 79 ++++++++++ test/factories/omiga_inscription_info.rb | 5 + test/factories/udt.rb | 36 ++++- .../ckb_sync/node_data_processor_test.rb | 80 ++++++++++ test/utils/ckb_utils_test.rb | 8 + vcr_fixtures/vcr_cassettes/blocks/31.yml | 39 +++++ vcr_fixtures/vcr_cassettes/blocks/32.yml | 39 +++++ 23 files changed, 760 insertions(+), 118 deletions(-) create mode 100644 app/controllers/api/v1/omiga_inscriptions_controller.rb create mode 100644 app/models/omiga_inscription_info.rb create mode 100644 app/serializers/omiga_inscription_info_serializer.rb create mode 100644 db/migrate/20240107100346_create_omiga_inscription_info.rb create mode 100644 test/controllers/api/v1/omiga_inscriptions_controller_test.rb create mode 100644 test/factories/omiga_inscription_info.rb create mode 100644 vcr_fixtures/vcr_cassettes/blocks/31.yml create mode 100644 vcr_fixtures/vcr_cassettes/blocks/32.yml diff --git a/app/controllers/api/v1/omiga_inscriptions_controller.rb b/app/controllers/api/v1/omiga_inscriptions_controller.rb new file mode 100644 index 000000000..4658be821 --- /dev/null +++ b/app/controllers/api/v1/omiga_inscriptions_controller.rb @@ -0,0 +1,67 @@ +module Api + module V1 + class OmigaInscriptionsController < ApplicationController + before_action :validate_query_params, only: :show + before_action :validate_pagination_params, :pagination_params, + only: :index + + def index + udts = Udt.omiga_inscription + + if stale?(udts) + udts = sort_udts(udts).page(@page).per(@page_size).fast_page + options = FastJsonapi::PaginationMetaGenerator.new( + request:, + records: udts, + page: @page, + page_size: @page_size, + ).call + + render json: UdtSerializer.new(udts, options) + end + end + + def show + udt = Udt.find_by!(type_hash: params[:id]) + render json: UdtSerializer.new(udt) + rescue ActiveRecord::RecordNotFound + raise Api::V1::Exceptions::UdtNotFoundError + end + + private + + def validate_query_params + validator = Validations::Udt.new(params) + + if validator.invalid? + errors = validator.error_object[:errors] + status = validator.error_object[:status] + + render json: errors, status: + end + end + + def pagination_params + @page = params[:page] || 1 + @page_size = params[:page_size] || Udt.default_per_page + end + + def sort_udts(records) + sort, order = params.fetch(:sort, "id.desc").split(".", 2) + sort = + case sort + when "created_time" then "block_timestamp" + when "transactions" then "h24_ckb_transactions_count" + when "addresses_count" then "addresses_count" + else "id" + end + + if order.nil? || !order.match?(/^(asc|desc)$/i) + order = "asc" + end + + records.order("#{sort} #{order}") + end + end + end +end diff --git a/app/models/cell_input.rb b/app/models/cell_input.rb index 32be0d28f..df01bf062 100644 --- a/app/models/cell_input.rb +++ b/app/models/cell_input.rb @@ -5,12 +5,16 @@ class CellInput < ApplicationRecord belongs_to :previous_cell_output, class_name: "CellOutput", optional: true belongs_to :block, optional: true - delegate :lock_script, :type_script, to: :previous_cell_output, allow_nil: true + delegate :lock_script, :type_script, to: :previous_cell_output, + allow_nil: true enum cell_type: { normal: 0, nervos_dao_deposit: 1, nervos_dao_withdrawing: 2, udt: 3, m_nft_issuer: 4, m_nft_class: 5, m_nft_token: 6, nrc_721_token: 7, nrc_721_factory: 8, cota_registry: 9, - cota_regular: 10, spore_cluster: 11, spore_cell: 12 } + cota_regular: 10, spore_cluster: 11, spore_cell: 12, omiga_inscription_info: 13, omiga_inscription: 14, + xudt: 15 + } + def output previous_cell_output end @@ -24,17 +28,17 @@ def to_raw { previous_output: { index: "0x#{(previous_index || previous_cell_output.cell_index).to_s(16)}", - tx_hash: previous_tx_hash || previous_cell_output.tx_hash + tx_hash: previous_tx_hash || previous_cell_output.tx_hash, }, - since: hex_since + since: hex_since, } else { previous_output: { index: "0xffffffff", - tx_hash: "0x0000000000000000000000000000000000000000000000000000000000000000" + tx_hash: "0x0000000000000000000000000000000000000000000000000000000000000000", }, - since: hex_since + since: hex_since, } end end diff --git a/app/models/cell_output.rb b/app/models/cell_output.rb index 2f6bd8a3b..72950988c 100644 --- a/app/models/cell_output.rb +++ b/app/models/cell_output.rb @@ -16,7 +16,10 @@ class CellOutput < ApplicationRecord cota_registry: 9, cota_regular: 10, spore_cluster: 11, - spore_cell: 12 + spore_cell: 12, + omiga_inscription_info: 13, + omiga_inscription: 14, + xudt: 15 } belongs_to :ckb_transaction @@ -35,10 +38,12 @@ class CellOutput < ApplicationRecord belongs_to :lock_script belongs_to :type_script, optional: true - has_many :cell_dependencies, foreign_key: :contract_cell_id, dependent: :delete_all + has_many :cell_dependencies, foreign_key: :contract_cell_id, + dependent: :delete_all has_one :cell_datum, class_name: "CellDatum", dependent: :destroy_async accepts_nested_attributes_for :cell_datum - validates :capacity, presence: true, numericality: { greater_than_or_equal_to: 0 } + validates :capacity, presence: true, + numericality: { greater_than_or_equal_to: 0 } # on-chain cell outputs must be included in certain block validates :block, presence: true, if: -> { live? or dead? } @@ -50,7 +55,8 @@ class CellOutput < ApplicationRecord validates :consumed_by, presence: true, if: :dead? # cell output must not have consumed_by_id set when it's live - validates :consumed_by_id, :consumed_block_timestamp, must_be_nil: true, if: :live? + validates :consumed_by_id, :consumed_block_timestamp, must_be_nil: true, + if: :live? # consumed timestamp must be always greater than committed timestamp validates :consumed_block_timestamp, numericality: { greater_than_or_equal_to: :block_timestamp }, @@ -60,22 +66,32 @@ class CellOutput < ApplicationRecord attr_accessor :raw_address - scope :consumed_after, ->(block_timestamp) { where("consumed_block_timestamp >= ?", block_timestamp) } - scope :consumed_before, ->(block_timestamp) { where("consumed_block_timestamp <= ?", block_timestamp) } + scope :consumed_after, ->(block_timestamp) { + where("consumed_block_timestamp >= ?", block_timestamp) + } + scope :consumed_before, ->(block_timestamp) { + where("consumed_block_timestamp <= ?", block_timestamp) + } scope :consumed_between, ->(start_timestamp, end_timestamp) { consumed_after(start_timestamp).consumed_before(end_timestamp) } scope :unconsumed_at, ->(block_timestamp) { where("consumed_block_timestamp > ? or consumed_block_timestamp = 0 or consumed_block_timestamp is null", block_timestamp) } - scope :generated_after, ->(block_timestamp) { where("block_timestamp >= ?", block_timestamp) } - scope :generated_before, ->(block_timestamp) { where("block_timestamp <= ?", block_timestamp) } + scope :generated_after, ->(block_timestamp) { + where("block_timestamp >= ?", block_timestamp) + } + scope :generated_before, ->(block_timestamp) { + where("block_timestamp <= ?", block_timestamp) + } scope :generated_between, ->(start_timestamp, end_timestamp) { generated_after(start_timestamp).generated_before(end_timestamp) } scope :inner_block, ->(block_id) { where("block_id = ?", block_id) } scope :free, -> { where(type_hash: nil, data_hash: nil) } - scope :occupied, -> { where.not(type_hash: nil).or(where.not(data_hash: nil)) } + scope :occupied, -> { + where.not(type_hash: nil).or(where.not(data_hash: nil)) + } before_create :setup_address @@ -102,7 +118,10 @@ def binary_data end def setup_address - self.address = Address.find_or_create_by_address_hash(raw_address, block_timestamp) if raw_address + if raw_address + self.address = Address.find_or_create_by_address_hash(raw_address, + block_timestamp) + end end # @return [Boolean] @@ -133,20 +152,24 @@ def self.find_by_pointer(tx_hash, index) expires_in: 1.day) do tx_id = CkbTransaction.tx_committed.find_by_tx_hash(tx_hash)&.id Rails.logger.info("find_by_pointer: tx_hash: #{tx_hash}, index: #{index}, tx_id: #{tx_id}") - find_by(ckb_transaction_id: tx_id, cell_index: index.is_a?(String) ? index.hex : index) if tx_id + if tx_id + find_by(ckb_transaction_id: tx_id, + cell_index: index.is_a?(String) ? index.hex : index) + end end end def node_output lock = CKB::Types::Script.new(**lock_script.to_node) type = type_script.present? ? CKB::Types::Script.new(**type_script.to_node) : nil - CKB::Types::Output.new(capacity: capacity.to_i, lock: lock, type: type) + CKB::Types::Output.new(capacity: capacity.to_i, lock:, type:) end # calculate the actual size of the cell output on chain # @return [Integer] def calculate_bytesize - [8, binary_data&.bytesize || 0, lock_script.calculate_bytesize, type_script&.calculate_bytesize || 0].sum + [8, binary_data&.bytesize || 0, lock_script.calculate_bytesize, + type_script&.calculate_bytesize || 0].sum end def calculate_min_capacity @@ -157,22 +180,22 @@ def to_raw { capacity: "0x#{capacity.to_i.to_s(16)}", lock: lock_script&.to_node, - type: type_script&.to_node + type: type_script&.to_node, } end def udt_info return unless udt? - udt_info = Udt.find_by(type_hash: type_hash, published: true) + udt_info = Udt.find_by(type_hash:, published: true) CkbUtils.hash_value_to_s( symbol: udt_info&.symbol, amount: udt_amount, decimal: udt_info&.decimal, - type_hash: type_hash, + type_hash:, published: !!udt_info&.published, display_name: udt_info&.display_name, - uan: udt_info&.uan + uan: udt_info&.uan, ) end @@ -194,7 +217,8 @@ def m_nft_info parsed_class_data = CkbUtils.parse_token_class_data(m_nft_class_cell.data) value = { class_name: parsed_class_data.name, token_id: type_script.args[50..-1], - total: parsed_class_data.total } + total: parsed_class_data.total + } else value = { class_name: "", token_id: nil, total: "" } end @@ -209,32 +233,33 @@ def nrc_721_nft_info case cell_type when "nrc_721_factory" - factory_cell_type_script = self.type_script + factory_cell_type_script = type_script factory_cell = NrcFactoryCell.find_by(code_hash: factory_cell_type_script.code_hash, hash_type: factory_cell_type_script.hash_type, args: factory_cell_type_script.args, verified: true) value = { symbol: factory_cell&.symbol, - amount: self.udt_amount, + amount: udt_amount, decimal: "", - type_hash: self.type_hash, + type_hash:, published: factory_cell&.verified, display_name: factory_cell&.name, - nan: "" + nan: "", } when "nrc_721_token" - udt = Udt.find_by(type_hash: type_hash) - factory_cell = NrcFactoryCell.where(id: udt.nrc_factory_cell_id, verified: true).first + udt = Udt.find_by(type_hash:) + factory_cell = NrcFactoryCell.where(id: udt.nrc_factory_cell_id, + verified: true).first udt_account = UdtAccount.where(udt_id: udt.id).first value = { symbol: factory_cell&.symbol, amount: udt_account.nft_token_id, decimal: udt_account.decimal, - type_hash: type_hash, + type_hash:, published: true, display_name: udt_account.full_name, - uan: "" + uan: "", } else raise "invalid cell type" @@ -251,12 +276,12 @@ def create_token name: parsed_class_data.name, cell_id: id, icon_url: parsed_class_data.renderer, - creator_id: address.id + creator_id: address.id, ) when "m_nft_token" m_nft_class_type = TypeScript.where( code_hash: CkbSync::Api.instance.token_class_script_code_hash, - args: type_script.args[0..49] + args: type_script.args[0..49], ).first if m_nft_class_type.present? m_nft_class_cell = m_nft_class_type.cell_outputs.last @@ -266,12 +291,12 @@ def create_token name: parsed_class_data.name, cell_id: m_nft_class_cell.id, creator_id: m_nft_class_cell.address_id, - icon_url: parsed_class_data.renderer + icon_url: parsed_class_data.renderer, ) item = coll.items.find_or_create_by( token_id: type_script.args[50..-1].hex, owner_id: address_id, - cell_id: id + cell_id: id, ) end end @@ -340,16 +365,16 @@ def cota_registry_info return unless cota_registry? code_hash = CkbSync::Api.instance.cota_registry_code_hash - CkbUtils.hash_value_to_s(symbol: "", amount: self.udt_amount, decimal: "", type_hash: self.type_hash, - published: "true", display_name: "", uan: "", code_hash: code_hash) + CkbUtils.hash_value_to_s(symbol: "", amount: udt_amount, decimal: "", type_hash:, + published: "true", display_name: "", uan: "", code_hash:) end def cota_regular_info return unless cota_regular? code_hash = CkbSync::Api.instance.cota_regular_code_hash - CkbUtils.hash_value_to_s(symbol: "", amount: self.udt_amount, decimal: "", type_hash: self.type_hash, - published: "true", display_name: "", uan: "", code_hash: code_hash) + CkbUtils.hash_value_to_s(symbol: "", amount: udt_amount, decimal: "", type_hash:, + published: "true", display_name: "", uan: "", code_hash:) end end diff --git a/app/models/ckb_sync/api.rb b/app/models/ckb_sync/api.rb index 494797701..aae3a5cd6 100644 --- a/app/models/ckb_sync/api.rb +++ b/app/models/ckb_sync/api.rb @@ -13,7 +13,8 @@ def initialize @api = CKB::API.new(host: ENV["CKB_NODE_URL"], timeout_config: { open_timeout: 1, read_timeout: 3, - write_timeout: 1 }) + write_timeout: 1 + }) end def chain_type @@ -80,9 +81,21 @@ def spore_cell_code_hashes end end + def omiga_inscription_info_code_hash + Settings.omiga_inscription_info_code_hash + end + + def omiga_inscription_code_hash + Settings.omiga_inscription_code_hash + end + + def xudt_code_hash + Settings.xudt_code_hash + end + METHOD_NAMES.each do |name| define_method name do |*params| - call_rpc(name, params: params) + call_rpc(name, params:) end end @@ -96,7 +109,7 @@ def get_block_cycles(block_hash) def generate_json_rpc_id @@latest_json_rpc_id += 1 - return @@latest_json_rpc_id + @@latest_json_rpc_id end # in case that some method you call is not implemented in ruby sdk @@ -110,7 +123,7 @@ def directly_single_call_rpc(options) "id": generate_json_rpc_id, "jsonrpc": "2.0", "method": options[:method], - "params": options[:params] + "params": options[:params], } url = ENV["CKB_NODE_URL"] @@ -118,10 +131,8 @@ def directly_single_call_rpc(options) # Rails.logger.debug "== in directly_call_rpc, url: #{url}, payload: #{payload}" res = HTTP.post(url, json: payload) - result = JSON.parse res.to_s + JSON.parse res.to_s # Rails.logger.debug "== in directly_call_rpc result: #{result.inspect}" - - return result end # in case that some method you call is not implemented in ruby sdk @@ -148,7 +159,7 @@ def directly_batch_call_rpc(payload) result = JSON.parse res.to_s Rails.logger.debug "== in directly_batch_call_rpc result: #{result.inspect}" - return result + result end # this methods calls the ruby-sdk, but not directly from rpc diff --git a/app/models/ckb_sync/new_node_data_processor.rb b/app/models/ckb_sync/new_node_data_processor.rb index 57cfcc062..b925777c8 100644 --- a/app/models/ckb_sync/new_node_data_processor.rb +++ b/app/models/ckb_sync/new_node_data_processor.rb @@ -436,7 +436,7 @@ def update_or_create_udt_accounts!(local_block) new_udt_accounts_attributes = Set.new udt_accounts_attributes = Set.new local_block.cell_outputs.select(:id, :address_id, :type_hash, :cell_type, :type_script_id).each do |udt_output| - next unless udt_output.cell_type.in?(%w(udt m_nft_token nrc_721_token spore_cell)) + next unless udt_output.cell_type.in?(%w(udt m_nft_token nrc_721_token spore_cell omiga_inscription)) address = Address.find(udt_output.address_id) udt_type = udt_type(udt_output.cell_type) @@ -463,7 +463,7 @@ def update_or_create_udt_accounts!(local_block) local_block.ckb_transactions.pluck(:id).each do |tx_id| # iterator over each tx id for better sql performance CellOutput.where(consumed_by_id: tx_id).select(:id, :address_id, :type_hash, :cell_type).each do |udt_output| - next unless udt_output.cell_type.in?(%w(udt m_nft_token nrc_721_token spore_cell)) + next unless udt_output.cell_type.in?(%w(udt m_nft_token nrc_721_token spore_cell omiga_inscription)) address = Address.find(udt_output.address_id) udt_type = udt_type(udt_output.cell_type) @@ -482,6 +482,8 @@ def update_or_create_udt_accounts!(local_block) udt_account.destroy unless address.cell_outputs.live.nrc_721_token.where(type_hash: udt_output.type_hash).exists? when "spore_cell" udt_account.destroy unless address.cell_outputs.live.spore_cell.where(type_hash: udt_output.type_hash).exists? + when "omiga_inscription" + udt_account.destroy unless address.cell_outputs.live.omiga_inscription.where(type_hash: udt_output.type_hash).exists? end end end @@ -622,7 +624,11 @@ def build_udts!(local_block, outputs, outputs_data) outputs.each do |tx_index, items| items.each_with_index do |output, index| cell_type = cell_type(output.type, outputs_data[tx_index][index]) - next unless cell_type.in?(%w(udt m_nft_token nrc_721_token spore_cell)) + if cell_type == "omiga_inscription_info" + info = CkbUtils.parse_omiga_inscription_info(outputs_data[tx_index][index]) + OmigaInscriptionInfo.upsert(info.merge(output.type.to_h), unique_by: :udt_hash) + end + next unless cell_type.in?(%w(udt m_nft_token nrc_721_token spore_cell omiga_inscription)) type_hash = output.type.compute_hash unless Udt.where(type_hash: type_hash).exists? @@ -680,11 +686,18 @@ def build_udts!(local_block, outputs, outputs_data) end nft_token_attr[:published] = true end + if cell_type == "omiga_inscription" + info = OmigaInscriptionInfo.find_by!(udt_hash: type_hash) + nft_token_attr[:full_name] = info.name + nft_token_attr[:symbol] = info.symbol + nft_token_attr[:decimal] = info.decimal + nft_token_attr[:published] = true + end # fill issuer_address after publish the token # udts_attributes << { # type_hash: type_hash, udt_type: udt_type(cell_type), block_timestamp: local_block.timestamp, args: output.type.args, # code_hash: output.type.code_hash, hash_type: output.type.hash_type }.merge(nft_token_attr) - Udt.create_or_find_by!({ + udt = Udt.create_or_find_by!({ type_hash: type_hash, udt_type: udt_type(cell_type), block_timestamp: local_block.timestamp, @@ -692,6 +705,11 @@ def build_udts!(local_block, outputs, outputs_data) code_hash: output.type.code_hash, hash_type: output.type.hash_type }.merge(nft_token_attr)) + + if cell_type == "omiga_inscription" + info = OmigaInscriptionInfo.find_by(udt_hash: type_hash, udt_id: nil) + info && info.update!(udt_id: udt.id) + end end end end @@ -1009,6 +1027,10 @@ def build_cell_inputs( tags[tx_index] << "udt" udt_address_ids[tx_index] << address_id contained_udt_ids[tx_index] << Udt.where(type_hash: type_hash, udt_type: "sudt").pick(:id) + when "omiga_inscription" + tags[tx_index] << "omiga_inscription" + udt_address_ids[tx_index] << address_id + contained_udt_ids[tx_index] << Udt.where(type_hash: type_hash, udt_type: "omiga_inscription").pick(:id) when "nrc_721_token" tags[tx_index] << "nrc_721_token" udt_address_ids[tx_index] << address_id @@ -1064,6 +1086,10 @@ def build_cell_outputs!( tags[tx_index] << "udt" udt_address_ids[tx_index] << address.id contained_udt_ids[tx_index] << Udt.where(type_hash: item.type.compute_hash, udt_type: "sudt").pick(:id) + elsif attr[:cell_type] == "omiga_inscription" + tags[tx_index] << "omiga_inscription" + udt_address_ids[tx_index] << address_id + contained_udt_ids[tx_index] << Udt.where(type_hash: item.type.compute_hash, udt_type: "omiga_inscription").pick(:id) elsif attr[:cell_type].in?(%w(m_nft_token nrc_721_token spore_cell)) TokenTransferDetectWorker.perform_async(ckb_txs[tx_index]["id"]) end diff --git a/app/models/omiga_inscription_info.rb b/app/models/omiga_inscription_info.rb new file mode 100644 index 000000000..bd0ad4629 --- /dev/null +++ b/app/models/omiga_inscription_info.rb @@ -0,0 +1,29 @@ +class OmigaInscriptionInfo < ApplicationRecord + belongs_to :udt, optional: true + + enum mint_status: { minting: 0, closed: 1, rebase_start: 2 } +end + +# == Schema Information +# +# Table name: omiga_inscription_infos +# +# id :bigint not null, primary key +# code_hash :binary +# hash_type :string +# args :string +# decimal :decimal(, ) +# name :string +# symbol :string +# udt_hash :string +# expected_supply :decimal(, ) +# mint_limit :decimal(, ) +# mint_status :integer +# udt_id :bigint +# created_at :datetime not null +# updated_at :datetime not null +# +# Indexes +# +# index_omiga_inscription_infos_on_udt_hash (udt_hash) UNIQUE +# diff --git a/app/models/udt.rb b/app/models/udt.rb index 2d9645aad..1064902c1 100644 --- a/app/models/udt.rb +++ b/app/models/udt.rb @@ -2,17 +2,20 @@ class Udt < ApplicationRecord MAX_PAGINATES_PER = 100 belongs_to :nrc_factory_cell, optional: true - has_one :udt_verification + has_one :omiga_inscription_info - enum udt_type: { sudt: 0, m_nft_token: 1, nrc_721_token: 2, spore_cell: 3 } + enum udt_type: { sudt: 0, m_nft_token: 1, nrc_721_token: 2, spore_cell: 3, + omiga_inscription: 4 } validates_presence_of :total_amount validates_length_of :symbol, minimum: 1, maximum: 16, allow_nil: true validates_length_of :full_name, minimum: 1, maximum: 100, allow_nil: true - validates :decimal, numericality: { greater_than_or_equal_to: 0, less_than_or_equal_to: 39 }, allow_nil: true + validates :decimal, + numericality: { greater_than_or_equal_to: 0, less_than_or_equal_to: 39 }, allow_nil: true validates :total_amount, numericality: { greater_than_or_equal_to: 0 } - validates :email, format: { with: /\A(.+)@(.+)\z/, message: "Not a valid email" }, allow_nil: true + validates :email, + format: { with: /\A(.+)@(.+)\z/, message: "Not a valid email" }, allow_nil: true scope :query_by_name_or_symbl, ->(search) { where("lower(full_name) LIKE ? or lower(symbol) LIKE ?", "%#{search}%", "%#{search}%") @@ -23,9 +26,9 @@ class Udt < ApplicationRecord has_and_belongs_to_many :ckb_transactions, join_table: :udt_transactions def update_h24_ckb_transactions_count - if self.ckb_transactions.exists? - update(h24_ckb_transactions_count: self.ckb_transactions.where("block_timestamp >= ?", - CkbUtils.time_in_milliseconds(24.hours.ago)).count) + if ckb_transactions.exists? + update(h24_ckb_transactions_count: ckb_transactions.where("block_timestamp >= ?", + CkbUtils.time_in_milliseconds(24.hours.ago)).count) end end @@ -33,9 +36,9 @@ def type_script return unless published { - args: args, - code_hash: code_hash, - hash_type: hash_type + args:, + code_hash:, + hash_type:, } end end diff --git a/app/models/udt_account.rb b/app/models/udt_account.rb index 48077ee0f..e61976b03 100644 --- a/app/models/udt_account.rb +++ b/app/models/udt_account.rb @@ -1,5 +1,6 @@ class UdtAccount < ApplicationRecord - enum udt_type: { sudt: 0, m_nft_token: 1, nrc_721_token: 2, spore_cell: 3 } + enum udt_type: { sudt: 0, m_nft_token: 1, nrc_721_token: 2, spore_cell: 3, + omiga_inscription: 4 } belongs_to :address belongs_to :udt @@ -7,7 +8,8 @@ class UdtAccount < ApplicationRecord validates_presence_of :amount validates_length_of :symbol, minimum: 1, maximum: 16, allow_nil: true validates_length_of :full_name, minimum: 1, maximum: 100, allow_nil: true - validates :decimal, numericality: { greater_than_or_equal_to: 0, less_than_or_equal_to: 39 }, allow_nil: true + validates :decimal, + numericality: { greater_than_or_equal_to: 0, less_than_or_equal_to: 39 }, allow_nil: true validates :amount, numericality: { greater_than_or_equal_to: 0 } delegate :display_name, :uan, to: :udt @@ -16,7 +18,8 @@ class UdtAccount < ApplicationRecord scope :published, -> { where(published: true) } def udt_icon_file - Rails.cache.realize([self.class.name, "udt_icon_file", id], race_condition_ttl: 3.seconds, expires_in: 1.day) do + Rails.cache.realize([self.class.name, "udt_icon_file", id], + race_condition_ttl: 3.seconds, expires_in: 1.day) do udt.icon_file end end diff --git a/app/serializers/omiga_inscription_info_serializer.rb b/app/serializers/omiga_inscription_info_serializer.rb new file mode 100644 index 000000000..0e163b2a3 --- /dev/null +++ b/app/serializers/omiga_inscription_info_serializer.rb @@ -0,0 +1,18 @@ +class OmigaInscriptionInfoSerializer + include FastJsonapi::ObjectSerializer + + attributes :code_hash, :hash_type, :args, :name, :symbol, :udt_hash, + :mint_status + + attribute :decimal do |object| + object.decimal.to_s + end + + attribute :expected_supply do |object| + object.expected_supply.to_s + end + + attribute :mint_limit do |object| + object.mint_limit.to_s + end +end diff --git a/app/serializers/udt_serializer.rb b/app/serializers/udt_serializer.rb index feaca1f7a..a8ae703e8 100644 --- a/app/serializers/udt_serializer.rb +++ b/app/serializers/udt_serializer.rb @@ -1,7 +1,8 @@ class UdtSerializer include FastJsonapi::ObjectSerializer - attributes :symbol, :full_name, :icon_file, :published, :description, :type_hash, :type_script, :issuer_address, :display_name, :uan + attributes :symbol, :full_name, :icon_file, :published, :description, + :type_hash, :type_script, :issuer_address, :display_name, :uan attribute :total_amount do |object| object.total_amount.to_s @@ -18,4 +19,28 @@ class UdtSerializer attributes :created_at do |object| object.block_timestamp.to_s end + + attribute :mint_status, if: Proc.new { |record, _params| + record.udt_type == "omiga_inscription" + } do |object| + object.omiga_inscription_info.mint_status + end + + attribute :mint_limit, if: Proc.new { |record, _params| + record.udt_type == "omiga_inscription" + } do |object| + object.omiga_inscription_info.mint_limit.to_s + end + + attribute :expected_supply, if: Proc.new { |record, _params| + record.udt_type == "omiga_inscription" + } do |object| + object.omiga_inscription_info.expected_supply.to_s + end + + attribute :inscription_id, if: Proc.new { |record, _params| + record.udt_type == "omiga_inscription" + } do |object| + object.omiga_inscription_info.args + end end diff --git a/app/utils/ckb_utils.rb b/app/utils/ckb_utils.rb index 55e133c18..d9f2830dd 100644 --- a/app/utils/ckb_utils.rb +++ b/app/utils/ckb_utils.rb @@ -21,7 +21,9 @@ def self.block_cell_consumed(transactions) end def self.total_cell_capacity(transactions) - transactions.flat_map(&:outputs).reduce(0) { |memo, output| memo + output.capacity.to_i } + transactions.flat_map(&:outputs).reduce(0) do |memo, output| + memo + output.capacity.to_i + end end def self.miner_hash(cellbase) @@ -71,8 +73,9 @@ def self.parse_cellbase_witness(cellbase) args = "0x#{args_serialization.unpack1('H*')}" hash_type = hash_type_hex == "0x00" ? "data" : "type" - lock = CKB::Types::Script.new(code_hash: code_hash, args: args, hash_type: hash_type) - OpenStruct.new(lock: lock, message: "0x#{message}") + lock = CKB::Types::Script.new(code_hash:, args:, + hash_type:) + OpenStruct.new(lock:, message: "0x#{message}") end def self.miner_message(cellbase) @@ -80,7 +83,8 @@ def self.miner_message(cellbase) end def self.generate_address(lock_script, version = CKB::Address::Version::CKB2021) - CKB::Address.new(lock_script, mode: ENV["CKB_NET_MODE"], version: version).generate + CKB::Address.new(lock_script, mode: ENV["CKB_NET_MODE"], + version:).generate end def self.parse_address(address_hash) @@ -88,7 +92,9 @@ def self.parse_address(address_hash) end def self.block_reward(block_number, block_economic_state) - primary_reward(block_number, block_economic_state) + secondary_reward(block_number, block_economic_state) + primary_reward(block_number, + block_economic_state) + secondary_reward(block_number, + block_economic_state) end def self.base_reward(block_number, epoch_number) @@ -144,7 +150,8 @@ def self.parse_epoch_info(header) parsed_epoch = parse_epoch(epoch) start_number = header.number - parsed_epoch.index - OpenStruct.new(number: parsed_epoch.number, length: parsed_epoch.length, start_number: start_number) + OpenStruct.new(number: parsed_epoch.number, length: parsed_epoch.length, + start_number:) end # This field encodes the epoch number and the fraction position of this block in the epoch. @@ -159,7 +166,7 @@ def self.parse_epoch(epoch) OpenStruct.new( length: (epoch >> 40) & 0xFFFF, index: (epoch >> 24) & 0xFFFF, - number: (epoch) & 0xFFFFFF + number: epoch & 0xFFFFFF, ) end @@ -180,7 +187,8 @@ def self.ckb_transaction_fee(ckb_transaction, input_capacities, output_capacitie else return 0 if ckb_transaction["is_cellbase"] - if CellOutput.where(consumed_by_id: ckb_transaction["id"], cell_type: "nervos_dao_withdrawing").present? + if CellOutput.where(consumed_by_id: ckb_transaction["id"], + cell_type: "nervos_dao_withdrawing").present? dao_withdraw_tx_fee(ckb_transaction) else normal_tx_fee(input_capacities, output_capacities) @@ -206,7 +214,9 @@ def self.address_cell_consumed(address_hash) address_cell_consumed = 0 get_unspent_cells(address_hash).find_each do |cell_output| - address_cell_consumed += calculate_cell_min_capacity(cell_output.node_output, cell_output.data) + address_cell_consumed += calculate_cell_min_capacity( + cell_output.node_output, cell_output.data + ) end address_cell_consumed @@ -221,16 +231,20 @@ def self.update_block_reward!(current_block) return if block_economic_state.blank? reward = CkbUtils.block_reward(target_block.number, block_economic_state) - primary_reward = CkbUtils.primary_reward(target_block.number, block_economic_state) - secondary_reward = CkbUtils.secondary_reward(target_block.number, block_economic_state) - proposal_reward = CkbUtils.proposal_reward(target_block.number, block_economic_state) - commit_reward = CkbUtils.commit_reward(target_block.number, block_economic_state) + primary_reward = CkbUtils.primary_reward(target_block.number, + block_economic_state) + secondary_reward = CkbUtils.secondary_reward(target_block.number, + block_economic_state) + proposal_reward = CkbUtils.proposal_reward(target_block.number, + block_economic_state) + commit_reward = CkbUtils.commit_reward(target_block.number, + block_economic_state) target_block.update!(reward_status: "issued", - reward: reward, - primary_reward: primary_reward, - secondary_reward: secondary_reward, - commit_reward: commit_reward, - proposal_reward: proposal_reward) + reward:, + primary_reward:, + secondary_reward:, + commit_reward:, + proposal_reward:) current_block.update!(target_block_reward_status: "issued") end @@ -243,15 +257,18 @@ def self.calculate_received_tx_fee!(current_block) proposal_reward = cellbase.proposal_reward commit_reward = cellbase.commit_reward received_tx_fee = commit_reward + proposal_reward - target_block.update!(received_tx_fee: received_tx_fee, received_tx_fee_status: "calculated") + target_block.update!(received_tx_fee:, + received_tx_fee_status: "calculated") end def self.update_current_block_mining_info(block) return if block.blank? miner_address = block.miner_address - unless block.mining_infos.exists?(block_number: block.number, address: miner_address) - block.mining_infos.create!(block_number: block.number, address: miner_address, status: "mined") + unless block.mining_infos.exists?(block_number: block.number, + address: miner_address) + block.mining_infos.create!(block_number: block.number, + address: miner_address, status: "mined") miner_address.increment!(:mined_blocks_count) end end @@ -315,7 +332,7 @@ def self.compact_to_target(compact) end overflow = !mantissa.zero? && exponent > 32 - return ret, overflow + [ret, overflow] end def self.target_to_difficulty(target) @@ -356,7 +373,7 @@ def self.parse_dao(dao) s_i = bin_dao[16..23].unpack("Q<").pack("Q>").unpack1("H*").hex u_i = bin_dao[24..].unpack("Q<").pack("Q>").unpack1("H*").hex - OpenStruct.new(c_i: c_i, ar_i: ar_i, s_i: s_i, u_i: u_i) + OpenStruct.new(c_i:, ar_i:, s_i:, u_i:) end def self.parse_udt_cell_data(data) @@ -377,7 +394,9 @@ def self.decode_header_deps(raw_header_deps) end array_size = raw_header_deps.unpack1("S!") template = "S!#{'H64' * array_size}" - raw_header_deps.unpack(template.to_s).drop(1).compact.map { |hash| "#{Settings.default_hash_prefix}#{hash}" } + raw_header_deps.unpack(template.to_s).drop(1).compact.map do |hash| + "#{Settings.default_hash_prefix}#{hash}" + end end # detect cell type from type script and cell data @@ -389,13 +408,14 @@ def self.cell_type(type_script, output_data) Settings.dao_code_hash, Settings.dao_type_hash, Settings.sudt_cell_type_hash, Settings.sudt1_cell_type_hash, CkbSync::Api.instance.issuer_script_code_hash, CkbSync::Api.instance.token_class_script_code_hash, CkbSync::Api.instance.token_script_code_hash, CkbSync::Api.instance.cota_registry_code_hash, - CkbSync::Api.instance.cota_regular_code_hash + CkbSync::Api.instance.cota_regular_code_hash, CkbSync::Api.instance.omiga_inscription_info_code_hash, + CkbSync::Api.instance.xudt_code_hash ].include?(type_script&.code_hash) && type_script&.hash_type == "type") || is_nrc_721_token_cell?(output_data) || is_nrc_721_factory_cell?(output_data) || [ CkbSync::Api.instance.spore_cluster_code_hash, - *CkbSync::Api.instance.spore_cell_code_hashes + *CkbSync::Api.instance.spore_cell_code_hashes, ].include?(type_script&.code_hash) && type_script&.hash_type == "data1" case type_script&.code_hash @@ -425,6 +445,16 @@ def self.cell_type(type_script, output_data) "spore_cluster" when *CkbSync::Api.instance.spore_cell_code_hashes "spore_cell" + when CkbSync::Api.instance.omiga_inscription_info_code_hash + "omiga_inscription_info" + when CkbSync::Api.instance.omiga_inscription_info_code_hash + "omiga_inscription_info" + when CkbSync::Api.instance.xudt_code_hash + if OmigaInscriptionInfo.where(udt_hash: type_script.compute_hash).exists? + "omiga_inscription" + else + "xudt" + end else if is_nrc_721_token_cell?(output_data) "nrc_721_token" @@ -447,11 +477,13 @@ def self.parse_issuer_data(data) info_size = data[18..21].to_i(16) info = JSON.parse( [data[22..]].pack("H*").force_encoding("UTF-8").encode("UTF-8", invalid: :replace, - undef: :replace).delete("\u0000") + undef: :replace).delete("\u0000"), ) - OpenStruct.new(version: version, class_count: class_count, set_count: set_count, info_size: info_size, info: info) - rescue - OpenStruct.new(version: 0, class_count: 0, set_count: 0, info_size: 0, info: "") + OpenStruct.new(version:, class_count:, + set_count:, info_size:, info:) + rescue StandardError + OpenStruct.new(version: 0, class_count: 0, set_count: 0, info_size: 0, + info: "") end # Parse mNFT token class data information from cell data @@ -482,10 +514,11 @@ def self.parse_token_class_data(data) renderer_end_index = renderer_start_index + renderer_size * 2 - 1 renderer = [data[renderer_start_index, renderer_end_index]].pack("H*").force_encoding("UTF-8").encode("UTF-8", invalid: :replace, undef: :replace).delete("\u0000") - OpenStruct.new(version: version, total: total, issued: issued, configure: configure, name: name, - description: description, renderer: renderer) - rescue - OpenStruct.new(version: 0, total: 0, issued: 0, configure: 0, name: "", description: "", renderer: "") + OpenStruct.new(version:, total:, issued:, configure:, name:, + description:, renderer:) + rescue StandardError + OpenStruct.new(version: 0, total: 0, issued: 0, configure: 0, name: "", + description: "", renderer: "") end def self.generate_crc32(str) @@ -518,8 +551,10 @@ def self.parse_nrc_721_factory_data(data) factory_name_hex = data[arg_name_length, name_byte_size * 2] arg_symbol_length = 4 - symbol_byte_size = data[(factory_name_hex.length + arg_name_length), arg_symbol_length].to_i(16) - factory_symbol_hex = data[arg_name_length + factory_name_hex.length + arg_symbol_length, symbol_byte_size * 2] + symbol_byte_size = data[(factory_name_hex.length + arg_name_length), + arg_symbol_length].to_i(16) + factory_symbol_hex = data[arg_name_length + factory_name_hex.length + arg_symbol_length, + symbol_byte_size * 2] arg_base_token_uri_length = 4 base_token_uri_length = data[(arg_name_length + factory_name_hex.length + arg_symbol_length + factory_symbol_hex.length), @@ -546,7 +581,7 @@ def self.address_to_lock_hash(address) end def self.hex_since(int_since_value) - return "0x#{int_since_value.to_s(16).rjust(16, '0')}" + "0x#{int_since_value.to_s(16).rjust(16, '0')}" end def self.shannon_to_byte(shannon) @@ -555,7 +590,10 @@ def self.shannon_to_byte(shannon) def self.hexes_to_bins_sql(hex_strings) if hex_strings.is_a?(Array) && hex_strings.length > 0 - hex_strings.map { |hex_string| ActiveRecord::Base.sanitize_sql_array(["E'\\\\x%s'::bytea", hex_string.delete_prefix("0x")]) }.join(", ") + hex_strings.map do |hex_string| + ActiveRecord::Base.sanitize_sql_array(["E'\\\\x%s'::bytea", + hex_string.delete_prefix("0x")]) + end.join(", ") else [] end @@ -568,8 +606,8 @@ def self.parse_spore_cluster_data(hex_data) name = [data.slice(name_offset + 8..description_offset - 1)].pack("H*") description = [data.slice(description_offset + 8..-1)].pack("H*") name = "#{name[0, 97]}..." if name.length > 100 - { name: name, description: description } - rescue => _e + { name:, description: } + rescue StandardError => _e { name: nil, description: nil } end @@ -581,8 +619,24 @@ def self.parse_spore_cell_data(hex_data) content_type = [data.slice(content_type_offset + 8..content_offset - 1)].pack("H*") content = data.slice(content_offset + 8..cluster_id_offset - 1) cluster_id = data.slice(cluster_id_offset + 8..-1) - { content_type: content_type, content: content, cluster_id: cluster_id.nil? ? nil : "0x#{cluster_id}" } - rescue => _e + { content_type:, content:, + cluster_id: cluster_id.nil? ? nil : "0x#{cluster_id}" } + rescue StandardError => _e { content_type: nil, content: nil, cluster_id: nil } end + + def self.parse_omiga_inscription_info(hex_data) + data = hex_data.delete_prefix("0x") + decimal = "0x#{data.slice!(0, 2)}".to_i(16) + name_len = "0x#{data.slice!(0, 2)}".to_i(16) + name = [data.slice!(0, name_len * 2)].pack("H*") + symbol_len = "0x#{data.slice!(0, 2)}".to_i(16) + symbol = [data.slice!(0, symbol_len * 2)].pack("H*") + udt_hash = "0x#{data.slice!(0, 64)}" + expected_supply = [data.slice!(0, 32)].pack("H*").unpack1("Q<2") + mint_limit = [data.slice!(0, 32)].pack("H*").unpack1("Q<2") + mint_status = "0x#{data.slice!(0, 2)}".to_i(16) + { decimal:, name:, symbol:, udt_hash:, expected_supply:, + mint_limit:, mint_status: } + end end diff --git a/config/routes.rb b/config/routes.rb index e32ad9356..b02ea620d 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -24,9 +24,11 @@ resources :address_dao_transactions, only: :show resources :block_transactions, only: :show resources :addresses, only: :show - get "/transactions/:id", to: "ckb_transactions#show", as: "ckb_transaction" + get "/transactions/:id", to: "ckb_transactions#show", + as: "ckb_transaction" get "/transactions", to: "ckb_transactions#index", as: "ckb_transactions" - post "/transactions/query", to: "ckb_transactions#query", as: "query_ckb_transactions" + post "/transactions/query", to: "ckb_transactions#query", + as: "query_ckb_transactions" resources :cell_input_lock_scripts, only: :show resources :cell_input_type_scripts, only: :show resources :cell_input_data, only: :show @@ -51,12 +53,13 @@ resources :daily_statistics, only: :show resources :block_statistics, only: :show ## TODO: unused route resources :epoch_statistics, only: :show - resources :market_data, only: [:index, :show] + resources :market_data, only: %i[index show] resources :udts, only: %i(index show update) do collection do get :download_csv end end + resources :omiga_inscriptions, only: %i(index show) resources :udt_transactions, only: :show resources :address_udt_transactions, only: :show resources :distribution_data, only: :show @@ -66,5 +69,6 @@ end end draw "v2" - match "/:anything" => "errors#routing_error", via: :all, constraints: { anything: /.*/ } + match "/:anything" => "errors#routing_error", via: :all, + constraints: { anything: /.*/ } end diff --git a/config/settings.mainnet.yml b/config/settings.mainnet.yml index 31f771387..7662437c7 100644 --- a/config/settings.mainnet.yml +++ b/config/settings.mainnet.yml @@ -24,6 +24,13 @@ nrc_721_token_output_data_header: "0x0ddeff3e8ee03cbf6a2c6920d05c381e" spore_cluster_code_hash: "" spore_cell1_code_hash: "" +# omiga inscription info +omiga_inscription_info_code_hash: "" +omiga_inscription_code_hash: "" + +# xudt +xudt_code_hash: "" + # hash length of an attribute(especially which comes from bytea column), # e.g. Block.uncle_block_hashes: "0x587f354162afd133b4a4f7a4b621d11e043c3c08b0af2801f1686b5403b14953", which has a length of 66 ( 2 + 64) default_hash_length: "64" diff --git a/config/settings.testnet.yml b/config/settings.testnet.yml index 0ed0f21f1..a412b3311 100644 --- a/config/settings.testnet.yml +++ b/config/settings.testnet.yml @@ -25,6 +25,12 @@ spore_cluster_code_hash: "0x598d793defef36e2eeba54a9b45130e4ca92822e1d193671f490 spore_cell1_code_hash: "0xc1a7e2d2bd7e0fa90e2f1121782aa9f71204d1fee3a634bf3b12c61a69ee574f" spore_cell2_code_hash: "0xbbad126377d45f90a8ee120da988a2d7332c78ba8fd679aab478a19d6c133494" +# omiga inscription info +omiga_inscription_info_code_hash: "0x50fdea2d0030a8d0b3d69f883b471cab2a29cae6f01923f19cecac0f27fdaaa6" +omiga_inscription_code_hash: "0x3a241ceceede72a5f55c8fb985652690f09a517d6c9070f0df0d3572fa03fb70" +# xudt +xudt_code_hash: "0x25c29dc317811a6f6f3985a7a9ebc4838bd388d19d0feeecf0bcd60f6c0975bb" + # hash length of an attribute(especially which comes from bytea column), # e.g. Block.uncle_block_hashes: "0x587f354162afd133b4a4f7a4b621d11e043c3c08b0af2801f1686b5403b14953", which has a length of 66 ( 2 + 64) default_hash_length: "64" diff --git a/db/migrate/20240107100346_create_omiga_inscription_info.rb b/db/migrate/20240107100346_create_omiga_inscription_info.rb new file mode 100644 index 000000000..10e1aea84 --- /dev/null +++ b/db/migrate/20240107100346_create_omiga_inscription_info.rb @@ -0,0 +1,20 @@ +class CreateOmigaInscriptionInfo < ActiveRecord::Migration[7.0] + def change + create_table :omiga_inscription_infos do |t| + t.binary :code_hash + t.string :hash_type + t.string :args + t.decimal :decimal + t.string :name + t.string :symbol + t.string :udt_hash + t.decimal :expected_supply + t.decimal :mint_limit + t.integer :mint_status + t.bigint :udt_id + + t.timestamps + t.index ["udt_hash"], name: "index_omiga_inscription_infos_on_udt_hash", unique: true + end + end +end diff --git a/db/structure.sql b/db/structure.sql index a7fcda3ce..4ac02264f 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -1650,6 +1650,47 @@ CREATE SEQUENCE public.old_ckb_transactions_id_seq ALTER SEQUENCE public.old_ckb_transactions_id_seq OWNED BY public.old_ckb_transactions.id; +-- +-- Name: omiga_inscription_infos; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.omiga_inscription_infos ( + id bigint NOT NULL, + code_hash bytea, + hash_type character varying, + args character varying, + "decimal" numeric, + name character varying, + symbol character varying, + udt_hash character varying, + expected_supply numeric, + mint_limit numeric, + mint_status integer, + udt_id bigint, + created_at timestamp(6) without time zone NOT NULL, + updated_at timestamp(6) without time zone NOT NULL +); + + +-- +-- Name: omiga_inscription_infos_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.omiga_inscription_infos_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: omiga_inscription_infos_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.omiga_inscription_infos_id_seq OWNED BY public.omiga_inscription_infos.id; + + -- -- Name: pool_transaction_entries; Type: TABLE; Schema: public; Owner: - -- @@ -2581,6 +2622,13 @@ ALTER TABLE ONLY public.nrc_factory_cells ALTER COLUMN id SET DEFAULT nextval('p ALTER TABLE ONLY public.old_ckb_transactions ALTER COLUMN id SET DEFAULT nextval('public.old_ckb_transactions_id_seq'::regclass); +-- +-- Name: omiga_inscription_infos id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.omiga_inscription_infos ALTER COLUMN id SET DEFAULT nextval('public.omiga_inscription_infos_id_seq'::regclass); + + -- -- Name: pool_transaction_entries id; Type: DEFAULT; Schema: public; Owner: - -- @@ -3011,6 +3059,14 @@ ALTER TABLE ONLY public.old_ckb_transactions ADD CONSTRAINT old_ckb_transactions_pkey PRIMARY KEY (id); +-- +-- Name: omiga_inscription_infos omiga_inscription_infos_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.omiga_inscription_infos + ADD CONSTRAINT omiga_inscription_infos_pkey PRIMARY KEY (id); + + -- -- Name: pool_transaction_entries pool_transaction_entries_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- @@ -3945,6 +4001,13 @@ CREATE UNIQUE INDEX index_old_ckb_transactions_on_tx_hash_and_block_id ON public CREATE INDEX index_old_ckb_transactions_on_udt_address_ids ON public.old_ckb_transactions USING gin (udt_address_ids); +-- +-- Name: index_omiga_inscription_infos_on_udt_hash; Type: INDEX; Schema: public; Owner: - +-- + +CREATE UNIQUE INDEX index_omiga_inscription_infos_on_udt_hash ON public.omiga_inscription_infos USING btree (udt_hash); + + -- -- Name: index_pool_transaction_entries_on_id_and_tx_status; Type: INDEX; Schema: public; Owner: - -- @@ -4752,6 +4815,7 @@ INSERT INTO "schema_migrations" (version) VALUES ('20230914120928'), ('20230918033957'), ('20231017074221'), -('20231218082938'); +('20231218082938'), +('20240107100346'); diff --git a/test/controllers/api/v1/omiga_inscriptions_controller_test.rb b/test/controllers/api/v1/omiga_inscriptions_controller_test.rb new file mode 100644 index 000000000..cd8dd5654 --- /dev/null +++ b/test/controllers/api/v1/omiga_inscriptions_controller_test.rb @@ -0,0 +1,79 @@ +require "test_helper" + +module Api + module V1 + class OmigaInscriptionsControllerTest < ActionDispatch::IntegrationTest + test "should get success code when call show" do + udt = create(:udt, :omiga_inscription) + + valid_get api_v1_omiga_inscription_url(udt.type_hash) + + assert_response :success + end + + test "should set right content type when call show" do + udt = create(:udt, :omiga_inscription) + + valid_get api_v1_omiga_inscription_url(udt.type_hash) + + assert_equal "application/vnd.api+json", response.media_type + end + + test "should respond with 415 Unsupported Media Type when Content-Type is wrong" do + udt = create(:udt, :omiga_inscription) + + get api_v1_omiga_inscription_url(udt.type_hash), + headers: { "Content-Type": "text/plain" } + + assert_equal 415, response.status + end + + test "should return corresponding udt with given type hash" do + udt = create(:udt, :omiga_inscription) + + valid_get api_v1_omiga_inscription_url(udt.type_hash) + + assert_equal UdtSerializer.new(udt).serialized_json, + response.body + end + + test "should contain right keys in the serialized object when call show" do + udt = create(:udt, :omiga_inscription) + + valid_get api_v1_omiga_inscription_url(udt.type_hash) + + response_udt = json["data"] + assert_equal %w( + symbol full_name display_name uan total_amount addresses_count + decimal icon_file h24_ckb_transactions_count created_at description + published type_hash type_script issuer_address mint_status mint_limit expected_supply inscription_id + ).sort, + response_udt["attributes"].keys.sort + end + + test "should get success code when call index" do + valid_get api_v1_omiga_inscriptions_url + assert_response :success + end + + test "should set right content type when call index" do + valid_get api_v1_omiga_inscriptions_url + + assert_equal "application/vnd.api+json", response.media_type + end + + test "should get empty array when there are no udts" do + valid_get api_v1_omiga_inscriptions_url + + assert_empty json["data"] + end + + test "should return omiga_inscription udts" do + create_list(:udt, 2, :omiga_inscription) + valid_get api_v1_omiga_inscriptions_url + + assert_equal 2, json["data"].length + end + end + end +end diff --git a/test/factories/omiga_inscription_info.rb b/test/factories/omiga_inscription_info.rb new file mode 100644 index 000000000..cd03b64e9 --- /dev/null +++ b/test/factories/omiga_inscription_info.rb @@ -0,0 +1,5 @@ +FactoryBot.define do + factory :omiga_inscription_info do + udt_hash { "0x#{SecureRandom.hex(32)}" } + end +end diff --git a/test/factories/udt.rb b/test/factories/udt.rb index daf24fb09..8b9fd26da 100644 --- a/test/factories/udt.rb +++ b/test/factories/udt.rb @@ -15,20 +15,46 @@ full_udt_address_ids = [] 20.times do block = create(:block, :with_block_hash) - transaction = create(:ckb_transaction, block: block, contained_udt_ids: [udt.id], tags: ["udt"]) - transaction1 = create(:ckb_transaction, block: block, contained_udt_ids: [udt.id], tags: ["udt"]) - cell_output = create(:cell_output, block: block, + transaction = create(:ckb_transaction, block:, + contained_udt_ids: [udt.id], tags: ["udt"]) + transaction1 = create(:ckb_transaction, block:, + contained_udt_ids: [udt.id], tags: ["udt"]) + cell_output = create(:cell_output, block:, ckb_transaction: transaction, consumed_by: transaction1, status: "dead", type_hash: udt.type_hash, cell_type: "udt", data: "0x000050ad321ea12e0000000000000000") - full_udt_address_ids << { address_id: cell_output.address.id, ckb_transaction_id: transaction.id } + full_udt_address_ids << { address_id: cell_output.address.id, + ckb_transaction_id: transaction.id } end udt.update(ckb_transactions_count: 40) AddressUdtTransaction.upsert_all full_udt_address_ids, - unique_by: [:address_id, :ckb_transaction_id] + unique_by: %i[address_id + ckb_transaction_id] + end + end + + trait :omiga_inscription do + udt_type { "omiga_inscription" } + decimal { 0.8e1 } + full_name { "CKB Fist Inscription" } + symbol { "CKBI" } + published { true } + after(:create) do |udt, _evaluator| + create(:omiga_inscription_info, + code_hash: "0x50fdea2d0030a8d0b3d69f883b471cab2a29cae6f01923f19cecac0f27fdaaa6", + hash_type: "type", + args: "0xcd89d8f36593a9a82501c024c5cdc4877ca11c5b3d5831b3e78334aecb978f0d", + decimal: udt.decimal, + name: udt.full_name, + symbol: udt.symbol, + udt_hash: udt.type_hash, + expected_supply: 0.21e16, + mint_limit: 0.1e12, + mint_status: "minting", + udt_id: udt.id) end end end diff --git a/test/models/ckb_sync/node_data_processor_test.rb b/test/models/ckb_sync/node_data_processor_test.rb index 0bf616845..33c81f32a 100644 --- a/test/models/ckb_sync/node_data_processor_test.rb +++ b/test/models/ckb_sync/node_data_processor_test.rb @@ -3592,6 +3592,86 @@ class NodeDataProcessorTest < ActiveSupport::TestCase assert_equal "R+K V1 N1", old_factory_cell.reload.symbol end + test "save omiga inscription info" do + CkbSync::Api.any_instance.stubs(:xudt_code_hash).returns("0x25c29dc317811a6f6f3985a7a9ebc4838bd388d19d0feeecf0bcd60f6c0975bb") + CkbSync::Api.any_instance.stubs(:omiga_inscription_info_code_hash).returns("0x50fdea2d0030a8d0b3d69f883b471cab2a29cae6f01923f19cecac0f27fdaaa6") + VCR.use_cassette("blocks/31") do + node_block = CkbSync::Api.instance.get_block_by_number(31) + block1 = create(:block, :with_block_hash, number: node_block.header.number - 1) + tx1 = create(:ckb_transaction, block: block1, tx_hash: "0x3e89753ebca825e1504498eb18b56576d5b7eff59fe033346a10ab9e8ca359a4") + input_address1 = create(:address) + address1_lock = create(:lock_script, address_id: input_address1.id, + args: "0x#{SecureRandom.hex(20)}", + code_hash: Settings.secp_cell_type_hash, + hash_type: "type") + output1 = create(:cell_output, ckb_transaction: tx1, + block: block1, capacity: 50000000 * 10**8, + tx_hash: tx1.tx_hash, + cell_index: 1, + address: input_address1, + cell_type: "normal", + lock_script_id: address1_lock.id, + type_script_id: nil) + node_data_processor.process_block(node_block) + assert_equal CellOutput.find_by(tx_hash: "0xb865e4d50a72f08acf45389fcd1f76eefe6eb3377733ffc3c1b934a57a86b5dc", cell_index: 0).cell_type, "omiga_inscription_info" + info = OmigaInscriptionInfo.first + assert_equal info.code_hash, "0x50fdea2d0030a8d0b3d69f883b471cab2a29cae6f01923f19cecac0f27fdaaa6" + assert_equal info.hash_type, "type" + assert_equal info.args, "0xcd89d8f36593a9a82501c024c5cdc4877ca11c5b3d5831b3e78334aecb978f0d" + assert_equal info.decimal, 0.8e1 + assert_equal info.name, "CKB Fist Inscription" + assert_equal info.symbol, "CKBI" + assert_equal info.udt_hash, "0x5fa66c8d5f43914f85d3083e0529931883a5b0a14282f891201069f1b5067908" + assert_equal info.expected_supply, 0.21e16 + assert_equal info.mint_limit, 0.1e12 + assert_equal info.mint_status, "minting" + assert_equal info.udt_id, nil + end + end + + test "save omiga inscription udt" do + CkbSync::Api.any_instance.stubs(:xudt_code_hash).returns("0x25c29dc317811a6f6f3985a7a9ebc4838bd388d19d0feeecf0bcd60f6c0975bb") + CkbSync::Api.any_instance.stubs(:omiga_inscription_info_code_hash).returns("0x50fdea2d0030a8d0b3d69f883b471cab2a29cae6f01923f19cecac0f27fdaaa6") + + VCR.use_cassette("blocks/32") do + node_block = CkbSync::Api.instance.get_block_by_number(32) + block1 = create(:block, :with_block_hash, number: node_block.header.number - 1) + tx1 = create(:ckb_transaction, block: block1, tx_hash: "0x3e89753ebca825e1504498eb18b56576d5b7eff59fe033346a10ab9e8ca359a4") + input_address1 = create(:address) + address1_lock = create(:lock_script, address_id: input_address1.id, + args: "0x#{SecureRandom.hex(20)}", + code_hash: Settings.secp_cell_type_hash, + hash_type: "type") + output1 = create(:cell_output, ckb_transaction: tx1, + block: block1, capacity: 50000000 * 10**8, + tx_hash: tx1.tx_hash, + cell_index: 1, + address: input_address1, + cell_type: "normal", + lock_script_id: address1_lock.id, + type_script_id: nil) + create(:omiga_inscription_info, + code_hash: "0x50fdea2d0030a8d0b3d69f883b471cab2a29cae6f01923f19cecac0f27fdaaa6", + hash_type: "type", + args: "0xcd89d8f36593a9a82501c024c5cdc4877ca11c5b3d5831b3e78334aecb978f0d", + decimal: 0.8e1, + name: "CKB Fist Inscription", + symbol: "CKBI", + udt_hash: "0x5fa66c8d5f43914f85d3083e0529931883a5b0a14282f891201069f1b5067908", + expected_supply: 0.21e16, + mint_limit: 0.1e12, + mint_status: "minting", + udt_id: nil + ) + node_data_processor.process_block(node_block) + assert_equal 1, UdtAccount.count + assert_equal 1, UdtTransaction.count + omiga_inscription = Udt.first + assert_equal OmigaInscriptionInfo.first.udt_id, omiga_inscription.id + assert_equal omiga_inscription.type_hash, "0x5fa66c8d5f43914f85d3083e0529931883a5b0a14282f891201069f1b5067908" + end + end + private def node_data_processor diff --git a/test/utils/ckb_utils_test.rb b/test/utils/ckb_utils_test.rb index c63fda26d..f871b1a23 100644 --- a/test/utils/ckb_utils_test.rb +++ b/test/utils/ckb_utils_test.rb @@ -453,6 +453,14 @@ class CkbUtilsTest < ActiveSupport::TestCase assert_equal info[:cluster_id], nil end + test "parse omiga inscription info data" do + data = "0x0814434b42204669737420496e736372697074696f6e04434b4249e0f8e095d975e21e1b451b582c9d0685104471d377c6589339b723f76c035c740040075af0750700000000000000000000e8764817000000000000000000000000" + info = CkbUtils.parse_omiga_inscription_info(data) + assert_equal info, + { decimal: 8, name: "CKB Fist Inscription", symbol: "CKBI", + udt_hash: "0xe0f8e095d975e21e1b451b582c9d0685104471d377c6589339b723f76c035c74", expected_supply: 2100000000000000, mint_limit: 100000000000, mint_status: 0 } + end + private def node_data_processor diff --git a/vcr_fixtures/vcr_cassettes/blocks/31.yml b/vcr_fixtures/vcr_cassettes/blocks/31.yml new file mode 100644 index 000000000..e3afacdce --- /dev/null +++ b/vcr_fixtures/vcr_cassettes/blocks/31.yml @@ -0,0 +1,39 @@ +--- +http_interactions: +- request: + method: post + uri: http://localhost:8114/ + body: + encoding: UTF-8 + string: '{"id":1,"jsonrpc":"2.0","method":"get_block_by_number","params":["0x1f","0x2",false]}' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Content-Type: + - application/json + Connection: + - keep-alive + Keep-Alive: + - '30' + response: + status: + code: 200 + message: OK + headers: + Content-Type: + - application/json; charset=utf-8 + Content-Length: + - '2138' + Date: + - Fri, 04 Oct 2019 15:54:13 GMT + body: + encoding: UTF-8 + string: '{"jsonrpc":"2.0","result":{"extension":"0x8ff8775a749aeefe169b9c176f690e47153c22ad55cca6694ab83469f5069cd2","header":{"compact_target":"0x1d08cdb1","dao":"0x2c34e8cb67565c4a014fecab67c82700a949185bc912d8050069153ba929cf08","epoch":"0x70803ba001ed5","extra_hash":"0x5fae5826e29a9ab5eeb87c02c2b9407fff2f5c4d6297f62f046160d6f92b9d3f","hash":"0x41800338f56ee284ba01322b3bbab976d791fda1676f56f78362cff317051f81","nonce":"0x8070e69daad54b7cb60d3ed99c57cb48","number":"0x1f","parent_hash":"0x65fc1b48bedd9e7467c79a57d7190065161bd471f877eebb8328e679c645af3e","proposals_hash":"0x44206f032b013f233f1c8d9226050b62e444449f15fa0d061c6303ca83269d0f","timestamp":"0x18cba81ecbb","transactions_root":"0x90d3e8dc57f0df60ebca854a0288ce62a5951304e555a499d47e3359ccc1d2f5","version":"0x0"},"proposals":["0x45747e9d861a75cbd540","0xf52c6b5087f1cc42b8d4","0x2ca7a87c2f917551c4fc"],"transactions":[{"cell_deps":[],"hash":"0x9b07c0d38d1c042fa1f73c4948cb94d46db727983af694458d948bc6243f3e6b","header_deps":[],"inputs":[{"previous_output":{"index":"0xffffffff","tx_hash":"0x0000000000000000000000000000000000000000000000000000000000000000"},"since":"0xb3bf13"}],"outputs":[{"capacity":"0x19bf50e587","lock":{"args":"0xed9b7cab5f5143cf4f5471382c40dd5977cbcdef","code_hash":"0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8","hash_type":"type"},"type":null}],"outputs_data":["0x"],"version":"0x0","witnesses":["0x830000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000000450340178ae277261a838c89f9ccb76a190ed4b2a0000000000000020302e3131332e302d72633220283866663030323620323032332d31322d31392920deadbeef"]},{"cell_deps":[],"hash":"0xb865e4d50a72f08acf45389fcd1f76eefe6eb3377733ffc3c1b934a57a86b5dc","header_deps":[],"inputs":[{"previous_output":{"index":"0x1","tx_hash":"0x3e89753ebca825e1504498eb18b56576d5b7eff59fe033346a10ab9e8ca359a4"},"since":"0x0"}],"outputs":[{"capacity":"0x525433d00","lock":{"args":"0x00016091d93dbab12f16640fb3a0a8f1e77e03fbc51c","code_hash":"0xd23761b364210735c19c60561d213fb3beae2fd6172743719eff6920e020baac","hash_type":"type"},"type":{"args":"0xcd89d8f36593a9a82501c024c5cdc4877ca11c5b3d5831b3e78334aecb978f0d","code_hash":"0x50fdea2d0030a8d0b3d69f883b471cab2a29cae6f01923f19cecac0f27fdaaa6","hash_type":"type"}},{"capacity":"0x8be2d7b2e80","lock":{"args":"0x00016091d93dbab12f16640fb3a0a8f1e77e03fbc51c","code_hash":"0xd23761b364210735c19c60561d213fb3beae2fd6172743719eff6920e020baac","hash_type":"type"},"type":null}],"outputs_data":["0x0814434b42204669737420496e736372697074696f6e04434b42495fa66c8d5f43914f85d3083e0529931883a5b0a14282f891201069f1b50679080040075af0750700000000000000000000e8764817000000000000000000000000","0x"],"version":"0x0","witnesses":["0x6b010000100000006b0100006b01000057010000014599a5795423d54ab8e1f44f5c6ef5be9b1829beddb787bc732e4469d25f8c93e94afa393617f905bf1765c35dc38501a862b4b2f794a88b4f9010da02411a8562750a85da5bd5b6015c9b6c80a200681dcfca59db6c7779718a520df2dbd7628822f70e700530b910b6e5eaa0608c2118543086d9355e3b36afc8cfaab87dfb49960de5880e8c687434170f6476605b8fe4aeb9a28632c7995cf3ba831d97630162f9fb777b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a224d574a6b59544d304e4745794d57453359324578596d566d4e7a526b4e5752684f474d7a4e3246694d4455304f4752695a446b304f4463335a5759774d5759304d3259795a5755775a54497a5a575579595464685977222c226f726967696e223a22687474703a2f2f6c6f63616c686f73743a38303030222c2263726f73734f726967696e223a66616c73657d","0x"]}],"uncles":[]},"id":2} + ' + http_version: + recorded_at: Fri, 04 Oct 2019 15:54:13 GMT +recorded_with: VCR 5.0.0 diff --git a/vcr_fixtures/vcr_cassettes/blocks/32.yml b/vcr_fixtures/vcr_cassettes/blocks/32.yml new file mode 100644 index 000000000..c4e5a2467 --- /dev/null +++ b/vcr_fixtures/vcr_cassettes/blocks/32.yml @@ -0,0 +1,39 @@ +--- +http_interactions: +- request: + method: post + uri: http://localhost:8114/ + body: + encoding: UTF-8 + string: '{"id":1,"jsonrpc":"2.0","method":"get_block_by_number","params":["0x20","0x2",false]}' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + Content-Type: + - application/json + Connection: + - keep-alive + Keep-Alive: + - '30' + response: + status: + code: 200 + message: OK + headers: + Content-Type: + - application/json; charset=utf-8 + Content-Length: + - '2138' + Date: + - Fri, 04 Oct 2019 15:54:13 GMT + body: + encoding: UTF-8 + string: '{"jsonrpc":"2.0","result":{"extension":"0x8ff8775a749aeefe169b9c176f690e47153c22ad55cca6694ab83469f5069cd2","header":{"compact_target":"0x1d08cdb1","dao":"0x2c34e8cb67565c4a014fecab67c82700a949185bc912d8050069153ba929cf08","epoch":"0x70803ba001ed5","extra_hash":"0x5fae5826e29a9ab5eeb87c02c2b9407fff2f5c4d6297f62f046160d6f92b9d3f","hash":"0x41800338f56ee284ba01322b3bbab976d791fda1676f56f78362cff317051f81","nonce":"0x8070e69daad54b7cb60d3ed99c57cb48","number":"0x20","parent_hash":"0x65fc1b48bedd9e7467c79a57d7190065161bd471f877eebb8328e679c645af3e","proposals_hash":"0x44206f032b013f233f1c8d9226050b62e444449f15fa0d061c6303ca83269d0f","timestamp":"0x18cba81ecbb","transactions_root":"0x90d3e8dc57f0df60ebca854a0288ce62a5951304e555a499d47e3359ccc1d2f5","version":"0x0"},"proposals":["0x45747e9d861a75cbd540","0xf52c6b5087f1cc42b8d4","0x2ca7a87c2f917551c4fc"],"transactions":[{"cell_deps":[],"hash":"0x9b07c0d38d1c042fa1f73c4948cb94d46db727983af694458d948bc6243f3e6b","header_deps":[],"inputs":[{"previous_output":{"index":"0xffffffff","tx_hash":"0x0000000000000000000000000000000000000000000000000000000000000000"},"since":"0xb3bf13"}],"outputs":[{"capacity":"0x19bf50e587","lock":{"args":"0xed9b7cab5f5143cf4f5471382c40dd5977cbcdef","code_hash":"0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8","hash_type":"type"},"type":null}],"outputs_data":["0x"],"version":"0x0","witnesses":["0x830000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000000450340178ae277261a838c89f9ccb76a190ed4b2a0000000000000020302e3131332e302d72633220283866663030323620323032332d31322d31392920deadbeef"]},{"cell_deps":[],"hash":"0xd5d38a2096c10e5d0d55def7f2b3fe58779aad831fbc9dcd594446b1f0837430","header_deps":[],"inputs":[{"previous_output":{"index":"0x1","tx_hash":"0x3e89753ebca825e1504498eb18b56576d5b7eff59fe033346a10ab9e8ca359a4"},"since":"0x0"}],"outputs":[{"capacity":"0x8bacd36a610","lock":{"args":"0x00016091d93dbab12f16640fb3a0a8f1e77e03fbc51c","code_hash":"0xd23761b364210735c19c60561d213fb3beae2fd6172743719eff6920e020baac","hash_type":"type"},"type":null},{"capacity":"0x360447100","lock":{"args":"0x00016091d93dbab12f16640fb3a0a8f1e77e03fbc51c","code_hash":"0xd23761b364210735c19c60561d213fb3beae2fd6172743719eff6920e020baac","hash_type":"type"},"type":{"args":"0x9709d30fc21348ae1d28a197310a80aec3b8cdb5c93814d5e240f9fba85b76af","code_hash":"0x25c29dc317811a6f6f3985a7a9ebc4838bd388d19d0feeecf0bcd60f6c0975bb","hash_type":"type"}}],"outputs_data":["0x","0x00e87648170000000000000000000000"],"version":"0x0","witnesses":["0x6b010000100000006b0100006b01000057010000014599a5795423d54ab8e1f44f5c6ef5be9b1829beddb787bc732e4469d25f8c93e94afa393617f905bf1765c35dc38501a862b4b2f794a88b4f9010da02411a8575d113300d9d3fec54e24999cb8abda8735e682cb47718bd36da72408a9ebe3a924e8b2b19c3f1b9b055a3e6bebef48e50db67514bf00a4ce7f38845a67a95b049960de5880e8c687434170f6476605b8fe4aeb9a28632c7995cf3ba831d97630162f9fb777b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a22593256694d6a566a5a5467334d6a6469596a466959574e6c4e546c6c4e7a6c684f544269595745314d5467794e47526c4d4467345a6a426c593249794d7a59795a5451354f574a6b4e7a517a4e6a566b5a54526c4d41222c226f726967696e223a22687474703a2f2f6c6f63616c686f73743a38303030222c2263726f73734f726967696e223a66616c73657d","0x810000001000000010000000100000006d0000006d00000014000000690000006900000069000000550000001000000030000000310000003a241ceceede72a5f55c8fb985652690f09a517d6c9070f0df0d3572fa03fb7001200000005cfcab1fc499de7d33265b04d2de9cf2f91cc7c7a578642993b0912b31b6cf3904000000"]}],"uncles":[]},"id":2} + ' + http_version: + recorded_at: Fri, 04 Oct 2019 15:54:13 GMT +recorded_with: VCR 5.0.0 From 623f8f16f77066caa19204a30c605c3c61e44d8a Mon Sep 17 00:00:00 2001 From: Miles Zhang Date: Tue, 9 Jan 2024 17:42:17 +0800 Subject: [PATCH 2/8] feat: omiga inscription name and symbol can't be null string (#1560) Signed-off-by: Miles Zhang --- app/utils/ckb_utils.rb | 2 +- test/utils/ckb_utils_test.rb | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/app/utils/ckb_utils.rb b/app/utils/ckb_utils.rb index d9f2830dd..e4687e8b1 100644 --- a/app/utils/ckb_utils.rb +++ b/app/utils/ckb_utils.rb @@ -636,7 +636,7 @@ def self.parse_omiga_inscription_info(hex_data) expected_supply = [data.slice!(0, 32)].pack("H*").unpack1("Q<2") mint_limit = [data.slice!(0, 32)].pack("H*").unpack1("Q<2") mint_status = "0x#{data.slice!(0, 2)}".to_i(16) - { decimal:, name:, symbol:, udt_hash:, expected_supply:, + { decimal:, name: name.presence, symbol: symbol.presence, udt_hash:, expected_supply:, mint_limit:, mint_status: } end end diff --git a/test/utils/ckb_utils_test.rb b/test/utils/ckb_utils_test.rb index f871b1a23..5a8168ea6 100644 --- a/test/utils/ckb_utils_test.rb +++ b/test/utils/ckb_utils_test.rb @@ -461,6 +461,12 @@ class CkbUtilsTest < ActiveSupport::TestCase udt_hash: "0xe0f8e095d975e21e1b451b582c9d0685104471d377c6589339b723f76c035c74", expected_supply: 2100000000000000, mint_limit: 100000000000, mint_status: 0 } end + test "parse omiga inscription info data when name is null" do + data = "0x08004b42204669737420496e736372697074696f6e04434b4249e0f8e095d975e21e1b451b582c9d0685104471d377c6589339b723f76c035c740040075af0750700000000000000000000e8764817000000000000000000000000" + info = CkbUtils.parse_omiga_inscription_info(data) + assert_equal info[:name], nil + end + private def node_data_processor From d30f834272c2740bb8e5ebd5f20ec4f954f249b1 Mon Sep 17 00:00:00 2001 From: Miles Zhang Date: Tue, 9 Jan 2024 21:50:42 +0800 Subject: [PATCH 3/8] feat: parse udt amount of omiga inscription cell (#1561) Signed-off-by: Miles Zhang --- .../ckb_sync/new_node_data_processor.rb | 388 ++-- app/utils/ckb_utils.rb | 8 +- .../ckb_sync/node_data_processor_test.rb | 1665 +++++++++++------ test/utils/ckb_utils_test.rb | 6 + 4 files changed, 1296 insertions(+), 771 deletions(-) diff --git a/app/models/ckb_sync/new_node_data_processor.rb b/app/models/ckb_sync/new_node_data_processor.rb index b925777c8..60edaea99 100644 --- a/app/models/ckb_sync/new_node_data_processor.rb +++ b/app/models/ckb_sync/new_node_data_processor.rb @@ -42,15 +42,15 @@ def call ApplicationRecord.cache do process_block(target_block) end - self.reorg_started_at.delete + reorg_started_at.delete res else self.reorg_started_at = Time.now res = RevertBlockJob.perform_now(local_tip_block) - self.reorg_started_at.delete + reorg_started_at.delete res end - rescue => e + rescue StandardError => e Rails.logger.error e.message puts e.backtrace.join("\n") raise e @@ -68,7 +68,8 @@ def process_block(node_block, refresh_balance: true) outputs = @outputs = {} outputs_data = @outputs_data = {} @tx_cell_deps = {} - @ckb_txs = build_ckb_transactions!(node_block, local_block, inputs, outputs, outputs_data).to_a + @ckb_txs = build_ckb_transactions!(node_block, local_block, inputs, + outputs, outputs_data).to_a build_udts!(local_block, outputs, outputs_data) tags = [] @@ -117,9 +118,9 @@ def check_invalid_address(address) extra: { block: @tip_block_number, address: address.address_hash, - wrong_balance: wrong_balance, - wrong_balance_occupied: wrong_balance_occupied - } + wrong_balance:, + wrong_balance_occupied:, + }, ) end end @@ -128,7 +129,8 @@ def check_invalid_address(address) def generate_deployed_cells_and_referring_cells(local_block) local_block.ckb_transactions.each do |ckb_transaction| - DeployedCell.create_initial_data_for_ckb_transaction ckb_transaction, tx_cell_deps[ckb_transaction.tx_hash] + DeployedCell.create_initial_data_for_ckb_transaction ckb_transaction, + tx_cell_deps[ckb_transaction.tx_hash] ReferringCell.create_initial_data_for_ckb_transaction ckb_transaction end end @@ -166,7 +168,10 @@ def increase_records_count(local_block) block_counter.increment!(:count) ckb_transaction_counter = TableRecordCount.find_or_initialize_by(table_name: "ckb_transactions") normal_transactions = local_block.ckb_transactions.normal.count - ckb_transaction_counter.increment!(:count, normal_transactions.count) if normal_transactions.present? + if normal_transactions.present? + ckb_transaction_counter.increment!(:count, + normal_transactions.count) + end end def process_dao_events!(local_tip_block = @local_tip_block) @@ -174,28 +179,34 @@ def process_dao_events!(local_tip_block = @local_tip_block) new_dao_depositors = {} dao_contract = DaoContract.default_contract process_deposit_dao_events!(local_block, new_dao_depositors, dao_contract) - process_withdraw_dao_events!(local_block, new_dao_depositors, dao_contract) + process_withdraw_dao_events!(local_block, new_dao_depositors, + dao_contract) process_interest_dao_events!(local_block, dao_contract) - build_new_dao_depositor_events!(local_block, new_dao_depositors, dao_contract) + build_new_dao_depositor_events!(local_block, new_dao_depositors, + dao_contract) # update dao contract ckb_transactions_count dao_contract.increment!(:ckb_transactions_count, - local_block.ckb_transactions.where("tags @> array[?]::varchar[]", ["dao"]).count) + local_block.ckb_transactions.where( + "tags @> array[?]::varchar[]", ["dao"] + ).count) end - def build_new_dao_depositor_events!(local_block, new_dao_depositors, dao_contract) + def build_new_dao_depositor_events!(local_block, new_dao_depositors, +dao_contract) new_dao_events_attributes = [] new_dao_depositors.each do |address_id, ckb_transaction_id| new_dao_events_attributes << { - block_id: local_block.id, ckb_transaction_id: ckb_transaction_id, address_id: address_id, event_type: "new_dao_depositor", + block_id: local_block.id, ckb_transaction_id:, address_id:, event_type: "new_dao_depositor", value: 1, status: "processed", contract_id: dao_contract.id, block_timestamp: local_block.timestamp, created_at: Time.current, - updated_at: Time.current } + updated_at: Time.current + } end if new_dao_events_attributes.present? DaoEvent.insert_all!(new_dao_events_attributes) dao_contract.update!( - total_depositors_count: dao_contract.total_depositors_count + new_dao_events_attributes.size, depositors_count: dao_contract.depositors_count + new_dao_events_attributes.size + total_depositors_count: dao_contract.total_depositors_count + new_dao_events_attributes.size, depositors_count: dao_contract.depositors_count + new_dao_events_attributes.size, ) address_ids = [] new_dao_events_attributes.each do |dao_event_attr| @@ -208,7 +219,8 @@ def build_new_dao_depositor_events!(local_block, new_dao_depositors, dao_contrac # Process DAO withdraw # Warning:because DAO withdraw is also a cell, to the destination address of withdraw is the address of the withdraw cell output. # So it's possible that the deposit address is different with the withdraw address. - def process_withdraw_dao_events!(local_block, new_dao_depositors, dao_contract) + def process_withdraw_dao_events!(local_block, _new_dao_depositors, +dao_contract) dao_contract = DaoContract.default_contract withdraw_amount = 0 withdraw_transaction_ids = Set.new @@ -233,10 +245,13 @@ def process_withdraw_dao_events!(local_block, new_dao_depositors, dao_contract) addrs_withdraw_info[address.id] = { dao_deposit: address.dao_deposit.to_i - previous_cell_output.capacity, is_depositor: address.is_depositor, - created_at: address.created_at + created_at: address.created_at, } end - addrs_withdraw_info[address.id][:dao_deposit] = 0 if addrs_withdraw_info[address.id][:dao_deposit] < 0 + if addrs_withdraw_info[address.id][:dao_deposit] < 0 + addrs_withdraw_info[address.id][:dao_deposit] = + 0 + end dao_events_attributes << { ckb_transaction_id: dao_input.ckb_transaction_id, block_id: local_block.id, @@ -262,7 +277,7 @@ def process_withdraw_dao_events!(local_block, new_dao_depositors, dao_contract) status: "processed", contract_id: dao_contract.id, created_at: Time.current, - updated_at: Time.current + updated_at: Time.current, } else puts "Cannot find address dao for #{previous_cell_output.address_id}" @@ -277,7 +292,7 @@ def process_withdraw_dao_events!(local_block, new_dao_depositors, dao_contract) dao_contract.update!( total_deposit: dao_contract.total_deposit - withdraw_amount, withdraw_transactions_count: dao_contract.withdraw_transactions_count + withdraw_transaction_ids.size, - depositors_count: dao_contract.depositors_count - take_away_all_deposit_count + depositors_count: dao_contract.depositors_count - take_away_all_deposit_count, ) update_addresses_dao_info(addrs_withdraw_info) end @@ -304,7 +319,7 @@ def process_interest_dao_events!(local_block, dao_contract) addrs_withdraw_info[address.id] = { interest: address.interest.to_i + interest, is_depositor: address.is_depositor, - created_at: address.created_at + created_at: address.created_at, } end # addrs_withdraw_info[address.id][:dao_deposit] = 0 if addrs_withdraw_info[address.id][:dao_deposit] < 0 @@ -318,7 +333,7 @@ def process_interest_dao_events!(local_block, dao_contract) status: "processed", contract_id: dao_contract.id, created_at: Time.current, - updated_at: Time.current + updated_at: Time.current, } address_dao_deposit = Address.where(id: previous_cell_output.address_id).pick(:dao_deposit) claimed_compensation += interest @@ -327,12 +342,13 @@ def process_interest_dao_events!(local_block, dao_contract) end # update dao contract info dao_contract.update!( - claimed_compensation: dao_contract.claimed_compensation + claimed_compensation + claimed_compensation: dao_contract.claimed_compensation + claimed_compensation, ) update_addresses_dao_info(addrs_withdraw_info) end - def process_deposit_dao_events!(local_block, new_dao_depositors, dao_contract) + def process_deposit_dao_events!(local_block, new_dao_depositors, +dao_contract) deposit_amount = 0 deposit_transaction_ids = Set.new addresses_deposit_info = {} @@ -351,7 +367,7 @@ def process_deposit_dao_events!(local_block, new_dao_depositors, dao_contract) dao_deposit: address.dao_deposit.to_i + dao_output.capacity, interest: address.interest, is_depositor: address.is_depositor, - created_at: address.created_at + created_at: address.created_at, } end if address.dao_deposit.zero? && !new_dao_depositors.key?(address.id) @@ -369,7 +385,7 @@ def process_deposit_dao_events!(local_block, new_dao_depositors, dao_contract) contract_id: dao_contract.id, block_timestamp: local_block.timestamp, created_at: Time.current, - updated_at: Time.current + updated_at: Time.current, } end DaoEvent.insert_all!(deposit_dao_events_attributes) if deposit_dao_events_attributes.present? @@ -377,7 +393,7 @@ def process_deposit_dao_events!(local_block, new_dao_depositors, dao_contract) # update dao contract info dao_contract.update!( total_deposit: dao_contract.total_deposit + deposit_amount, - deposit_transactions_count: dao_contract.deposit_transactions_count + deposit_transaction_ids.size + deposit_transactions_count: dao_contract.deposit_transactions_count + deposit_transaction_ids.size, ) update_addresses_dao_info(addresses_deposit_info) end @@ -390,7 +406,7 @@ def update_addresses_dao_info(addrs_deposit_info) dao_deposit: address_info[:dao_deposit], interest: address_info[:interest], created_at: address_info[:created_at], - updated_at: Time.current + updated_at: Time.current, } end Address.upsert_all(addresses_deposit_attributes) if addresses_deposit_attributes.present? @@ -402,7 +418,8 @@ def update_udt_info(local_block) type_hashes << udt_output.type_hash end local_block.ckb_transactions.pluck(:id).each do |tx_id| - CellOutput.where(consumed_by_id: tx_id).udt.select(:id, :type_hash).each do |udt_output| + CellOutput.where(consumed_by_id: tx_id).udt.select(:id, + :type_hash).each do |udt_output| type_hashes << udt_output.type_hash end end @@ -412,16 +429,16 @@ def update_udt_info(local_block) addresses_count_info = UdtAccount.where(type_hash: type_hashes).group(:type_hash).count(:address_id) udts_attributes = Set.new type_hashes.each do |type_hash| - udt = Udt.where(type_hash: type_hash).select(:id).take! + udt = Udt.where(type_hash:).select(:id).take! ckb_transactions_count = Rails.cache.fetch("udt_txs_count_#{udt.id}", expires_in: 3600) do UdtTransaction.where(udt_id: udt.id).count end udts_attributes << { - type_hash: type_hash, + type_hash:, total_amount: amount_info[type_hash], addresses_count: addresses_count_info[type_hash], - ckb_transactions_count: ckb_transactions_count + ckb_transactions_count:, } end @@ -435,13 +452,15 @@ def update_udt_info(local_block) def update_or_create_udt_accounts!(local_block) new_udt_accounts_attributes = Set.new udt_accounts_attributes = Set.new - local_block.cell_outputs.select(:id, :address_id, :type_hash, :cell_type, :type_script_id).each do |udt_output| - next unless udt_output.cell_type.in?(%w(udt m_nft_token nrc_721_token spore_cell omiga_inscription)) + local_block.cell_outputs.select(:id, :address_id, :type_hash, :cell_type, + :type_script_id).each do |udt_output| + next unless udt_output.cell_type.in?(%w(udt m_nft_token nrc_721_token + spore_cell omiga_inscription)) address = Address.find(udt_output.address_id) udt_type = udt_type(udt_output.cell_type) - udt_account = address.udt_accounts.where(type_hash: udt_output.type_hash, udt_type: udt_type).select(:id, - :created_at).first + udt_account = address.udt_accounts.where(type_hash: udt_output.type_hash, udt_type:).select(:id, + :created_at).first amount = udt_account_amount(udt_type, udt_output.type_hash, address) nft_token_id = case udt_type @@ -450,40 +469,43 @@ def update_or_create_udt_accounts!(local_block) when "spore_cell" udt_output.type_script.args.hex end - udt = Udt.where(type_hash: udt_output.type_hash, udt_type: udt_type).select(:id, :udt_type, :full_name, - :symbol, :decimal, :published, :code_hash, :type_hash, :created_at).take! + udt = Udt.where(type_hash: udt_output.type_hash, udt_type:).select(:id, :udt_type, :full_name, + :symbol, :decimal, :published, :code_hash, :type_hash, :created_at).take! if udt_account.present? - udt_accounts_attributes << { id: udt_account.id, amount: amount, created_at: udt.created_at } + udt_accounts_attributes << { id: udt_account.id, amount:, + created_at: udt.created_at } else new_udt_accounts_attributes << { address_id: udt_output.address_id, udt_type: udt.udt_type, full_name: udt.full_name, symbol: udt.symbol, decimal: udt.decimal, - published: udt.published, code_hash: udt.code_hash, type_hash: udt.type_hash, amount: amount, udt_id: udt.id, nft_token_id: nft_token_id } + published: udt.published, code_hash: udt.code_hash, type_hash: udt.type_hash, amount:, udt_id: udt.id, nft_token_id: + } end end local_block.ckb_transactions.pluck(:id).each do |tx_id| # iterator over each tx id for better sql performance - CellOutput.where(consumed_by_id: tx_id).select(:id, :address_id, :type_hash, :cell_type).each do |udt_output| - next unless udt_output.cell_type.in?(%w(udt m_nft_token nrc_721_token spore_cell omiga_inscription)) + CellOutput.where(consumed_by_id: tx_id).select(:id, :address_id, + :type_hash, :cell_type).each do |udt_output| + next unless udt_output.cell_type.in?(%w(udt m_nft_token nrc_721_token + spore_cell omiga_inscription)) address = Address.find(udt_output.address_id) udt_type = udt_type(udt_output.cell_type) - udt_account = address.udt_accounts.where(type_hash: udt_output.type_hash, udt_type: udt_type).select(:id, - :created_at).first + udt_account = address.udt_accounts.where(type_hash: udt_output.type_hash, udt_type:).select(:id, + :created_at).first amount = udt_account_amount(udt_type, udt_output.type_hash, address) - udt = Udt.where(type_hash: udt_output.type_hash, udt_type: udt_type).select(:id, :udt_type, :full_name, - :symbol, :decimal, :published, :code_hash, :type_hash, :created_at).take! + udt = Udt.where(type_hash: udt_output.type_hash, udt_type:).select(:id, :udt_type, :full_name, + :symbol, :decimal, :published, :code_hash, :type_hash, :created_at).take! if udt_account.present? case udt_type - when "sudt" - udt_accounts_attributes << { id: udt_account.id, amount: amount, created_at: udt.created_at } + when "sudt", "omiga_inscription" + udt_accounts_attributes << { id: udt_account.id, amount:, + created_at: udt.created_at } when "m_nft_token" udt_account.destroy unless address.cell_outputs.live.m_nft_token.where(type_hash: udt_output.type_hash).exists? when "nrc_721_token" udt_account.destroy unless address.cell_outputs.live.nrc_721_token.where(type_hash: udt_output.type_hash).exists? when "spore_cell" udt_account.destroy unless address.cell_outputs.live.spore_cell.where(type_hash: udt_output.type_hash).exists? - when "omiga_inscription" - udt_account.destroy unless address.cell_outputs.live.omiga_inscription.where(type_hash: udt_output.type_hash).exists? end end end @@ -491,7 +513,8 @@ def update_or_create_udt_accounts!(local_block) if new_udt_accounts_attributes.present? UdtAccount.insert_all!(new_udt_accounts_attributes.map! do |attr| - attr.merge!(created_at: Time.current, updated_at: Time.current) + attr.merge!(created_at: Time.current, + updated_at: Time.current) end) end if udt_accounts_attributes.present? @@ -508,11 +531,13 @@ def udt_type(cell_type) def udt_account_amount(udt_type, type_hash, address) case udt_type when "sudt" - address.cell_outputs.live.udt.where(type_hash: type_hash).sum(:udt_amount) + address.cell_outputs.live.udt.where(type_hash:).sum(:udt_amount) + when "omiga_inscription" + address.cell_outputs.live.omiga_inscription.where(type_hash:).sum(:udt_amount) when "m_nft_token" - address.cell_outputs.live.m_nft_token.where(type_hash: type_hash).sum(:udt_amount) + address.cell_outputs.live.m_nft_token.where(type_hash:).sum(:udt_amount) when "spore_cell" - address.cell_outputs.live.spore_cell.where(type_hash: type_hash).sum(:udt_amount) + address.cell_outputs.live.spore_cell.where(type_hash:).sum(:udt_amount) else 0 end @@ -524,7 +549,10 @@ def update_table_records_count(local_block) block_counter.increment!(:count) ckb_transaction_counter = TableRecordCount.find_or_initialize_by(table_name: "ckb_transactions") normal_transactions = local_block.ckb_transactions.normal - ckb_transaction_counter.increment!(:count, normal_transactions.count) if normal_transactions.present? + if normal_transactions.present? + ckb_transaction_counter.increment!(:count, + normal_transactions.count) + end end def update_block_reward_info!(local_block) @@ -589,7 +617,7 @@ def update_addresses_info(addrs_change, local_block) balance_occupied: addr.balance_occupied + balance_occupied_diff, ckb_transactions_count: addr.ckb_transactions_count + ckb_txs_count, live_cells_count: addr.live_cells_count + live_cells_diff, - dao_transactions_count: addr.dao_transactions_count + dao_txs_count + dao_transactions_count: addr.dao_transactions_count + dao_txs_count, ) save_address_block_snapshot!(addr, local_block) @@ -604,11 +632,11 @@ def save_address_block_snapshot!(addr, local_block) balance_occupied: addr.balance_occupied, ckb_transactions_count: addr.ckb_transactions_count, live_cells_count: addr.live_cells_count, - dao_transactions_count: addr.dao_transactions_count - } + dao_transactions_count: addr.dao_transactions_count, + }, ).find_or_create_by!( address_id: addr.id, - block_id: local_block.id + block_id: local_block.id, ) end @@ -626,13 +654,16 @@ def build_udts!(local_block, outputs, outputs_data) cell_type = cell_type(output.type, outputs_data[tx_index][index]) if cell_type == "omiga_inscription_info" info = CkbUtils.parse_omiga_inscription_info(outputs_data[tx_index][index]) - OmigaInscriptionInfo.upsert(info.merge(output.type.to_h), unique_by: :udt_hash) + OmigaInscriptionInfo.upsert(info.merge(output.type.to_h), + unique_by: :udt_hash) end - next unless cell_type.in?(%w(udt m_nft_token nrc_721_token spore_cell omiga_inscription)) + next unless cell_type.in?(%w(udt m_nft_token nrc_721_token spore_cell + omiga_inscription)) type_hash = output.type.compute_hash - unless Udt.where(type_hash: type_hash).exists? - nft_token_attr = { full_name: nil, icon_file: nil, published: false, symbol: nil } + unless Udt.where(type_hash:).exists? + nft_token_attr = { full_name: nil, icon_file: nil, + published: false, symbol: nil } if cell_type == "m_nft_token" m_nft_class_type = TypeScript.where(code_hash: CkbSync::Api.instance.token_class_script_code_hash, args: output.type.args[0..49]).first @@ -644,7 +675,7 @@ def build_udts!(local_block, outputs, outputs_data) name: parsed_class_data.name, cell_id: m_nft_class_cell.id, icon_url: parsed_class_data.renderer, - creator_id: m_nft_class_cell.address_id + creator_id: m_nft_class_cell.address_id, ) nft_token_attr[:full_name] = parsed_class_data.name @@ -665,7 +696,7 @@ def build_udts!(local_block, outputs, outputs_data) name: parsed_cluster_data[:name], description: parsed_cluster_data[:description], cell_id: spore_cluster_cell.id, - creator_id: spore_cluster_cell.address_id + creator_id: spore_cluster_cell.address_id, ) nft_token_attr[:full_name] = parsed_cluster_data[:name] @@ -680,8 +711,10 @@ def build_udts!(local_block, outputs, outputs_data) args: factory_cell.args) if nrc_721_factory_cell.verified nft_token_attr[:full_name] = nrc_721_factory_cell.name - nft_token_attr[:symbol] = nrc_721_factory_cell.symbol.to_s[0, 16] - nft_token_attr[:icon_file] = "#{nrc_721_factory_cell.base_token_uri}/#{factory_cell.token_id}" + nft_token_attr[:symbol] = + nrc_721_factory_cell.symbol.to_s[0, 16] + nft_token_attr[:icon_file] = + "#{nrc_721_factory_cell.base_token_uri}/#{factory_cell.token_id}" nft_token_attr[:nrc_factory_cell_id] = nrc_721_factory_cell.id end nft_token_attr[:published] = true @@ -698,16 +731,17 @@ def build_udts!(local_block, outputs, outputs_data) # type_hash: type_hash, udt_type: udt_type(cell_type), block_timestamp: local_block.timestamp, args: output.type.args, # code_hash: output.type.code_hash, hash_type: output.type.hash_type }.merge(nft_token_attr) udt = Udt.create_or_find_by!({ - type_hash: type_hash, + type_hash:, udt_type: udt_type(cell_type), block_timestamp: local_block.timestamp, args: output.type.args, code_hash: output.type.code_hash, - hash_type: output.type.hash_type + hash_type: output.type.hash_type, }.merge(nft_token_attr)) if cell_type == "omiga_inscription" - info = OmigaInscriptionInfo.find_by(udt_hash: type_hash, udt_id: nil) + info = OmigaInscriptionInfo.find_by(udt_hash: type_hash, + udt_id: nil) info && info.update!(udt_id: udt.id) end end @@ -732,9 +766,15 @@ def update_ckb_txs_rel_and_fee( contained_addr_ids[tx_index].to_a.map do |a| { address_id: a, ckb_transaction_id: tx_id } end - full_dao_address_ids += dao_address_ids[tx_index].to_a.map { |a| { address_id: a, ckb_transaction_id: tx_id } } - full_tx_udt_ids += contained_udt_ids[tx_index].to_a.map { |u| { udt_id: u, ckb_transaction_id: tx_id } } - full_udt_address_ids += udt_address_ids[tx_index].to_a.map { |a| { address_id: a, ckb_transaction_id: tx_id } } + full_dao_address_ids += dao_address_ids[tx_index].to_a.map do |a| + { address_id: a, ckb_transaction_id: tx_id } + end + full_tx_udt_ids += contained_udt_ids[tx_index].to_a.map do |u| + { udt_id: u, ckb_transaction_id: tx_id } + end + full_udt_address_ids += udt_address_ids[tx_index].to_a.map do |a| + { address_id: a, ckb_transaction_id: tx_id } + end attr = { id: tx_id, @@ -749,7 +789,7 @@ def update_ckb_txs_rel_and_fee( output_capacities[tx_index]) end, created_at: tx["created_at"], - updated_at: Time.current + updated_at: Time.current, } # binding.pry if attr[:transaction_fee] < 0 @@ -758,19 +798,27 @@ def update_ckb_txs_rel_and_fee( end if ckb_transactions_attributes.present? - CkbTransaction.upsert_all(ckb_transactions_attributes, unique_by: [:id, :tx_status]) + CkbTransaction.upsert_all(ckb_transactions_attributes, + unique_by: %i[id tx_status]) end if full_tx_address_ids.present? - AccountBook.upsert_all full_tx_address_ids, unique_by: [:address_id, :ckb_transaction_id] + AccountBook.upsert_all full_tx_address_ids, + unique_by: %i[address_id ckb_transaction_id] + end + if full_tx_udt_ids.present? + UdtTransaction.upsert_all full_tx_udt_ids, + unique_by: %i[udt_id + ckb_transaction_id] end - UdtTransaction.upsert_all full_tx_udt_ids, unique_by: [:udt_id, :ckb_transaction_id] if full_tx_udt_ids.present? if full_dao_address_ids.present? AddressDaoTransaction.upsert_all full_dao_address_ids, - unique_by: [:address_id, :ckb_transaction_id] + unique_by: %i[address_id + ckb_transaction_id] end if full_udt_address_ids.present? AddressUdtTransaction.upsert_all full_udt_address_ids, - unique_by: [:address_id, :ckb_transaction_id] + unique_by: %i[address_id + ckb_transaction_id] end end @@ -788,17 +836,23 @@ def build_cells_and_locks!( type_script_ids = [] if lock_scripts_attributes.present? - lock_scripts_attributes.map! { |attr| attr.merge!(created_at: Time.current, updated_at: Time.current) } - lock_script_ids = LockScript.insert_all!(lock_scripts_attributes).map { |e| e["id"] } + lock_scripts_attributes.map! do |attr| + attr.merge!(created_at: Time.current, updated_at: Time.current) + end + lock_script_ids = LockScript.insert_all!(lock_scripts_attributes).map do |e| + e["id"] + end lock_script_ids.each do |lock_script_id| lock_script = LockScript.find lock_script_id contract = Contract.find_by code_hash: lock_script.code_hash - temp_hash = { script_hash: lock_script&.script_hash, is_contract: false } + temp_hash = { script_hash: lock_script&.script_hash, + is_contract: false } if contract - temp_hash = temp_hash.merge is_contract: true, contract_id: contract.id + temp_hash = temp_hash.merge is_contract: true, + contract_id: contract.id else contract = Contract.create code_hash: lock_script.script_hash temp_hash = temp_hash.merge contract_id: contract.id @@ -809,15 +863,21 @@ def build_cells_and_locks!( end if type_scripts_attributes.present? - type_scripts_attributes.map! { |attr| attr.merge!(created_at: Time.current, updated_at: Time.current) } - type_script_ids = TypeScript.insert_all!(type_scripts_attributes).map { |e| e["id"] } + type_scripts_attributes.map! do |attr| + attr.merge!(created_at: Time.current, updated_at: Time.current) + end + type_script_ids = TypeScript.insert_all!(type_scripts_attributes).map do |e| + e["id"] + end type_script_ids.each do |type_script_id| type_script = TypeScript.find(type_script_id) - temp_hash = { script_hash: type_script&.script_hash, is_contract: false } + temp_hash = { script_hash: type_script&.script_hash, + is_contract: false } contract = Contract.find_by code_hash: type_script.code_hash if contract - temp_hash = temp_hash.merge is_contract: true, contract_id: contract.id + temp_hash = temp_hash.merge is_contract: true, + contract_id: contract.id else contract = Contract.create code_hash: type_script.script_hash temp_hash = temp_hash.merge contract_id: contract.id @@ -832,8 +892,8 @@ def build_cells_and_locks!( build_cell_outputs!(node_block, outputs, ckb_txs, local_block, cell_outputs_attributes, output_capacities, tags, udt_address_ids, dao_address_ids, contained_udt_ids, contained_addr_ids, addrs_changes) if cell_outputs_attributes.present? - id_hashes = CellOutput.upsert_all(cell_outputs_attributes, unique_by: [:tx_hash, :cell_index], - returning: [:id, :data_hash]) + id_hashes = CellOutput.upsert_all(cell_outputs_attributes, unique_by: %i[tx_hash cell_index], + returning: %i[id data_hash]) cell_data_attrs = [] id_hashes.each do |row| @@ -841,7 +901,8 @@ def build_cells_and_locks!( if hash.present? hash[0] = "0" hash = CKB::Utils.hex_to_bin(hash) - cell_data_attrs << { cell_output_id: row["id"], data: @cell_datas[hash] } + cell_data_attrs << { cell_output_id: row["id"], + data: @cell_datas[hash] } end end @@ -856,15 +917,17 @@ def build_cells_and_locks!( input_capacities, tags, udt_address_ids, dao_address_ids, contained_udt_ids, contained_addr_ids, prev_outputs, addrs_changes) - CellInput.upsert_all(cell_inputs_attributes, unique_by: [:ckb_transaction_id, :index]) + CellInput.upsert_all(cell_inputs_attributes, + unique_by: %i[ckb_transaction_id index]) if prev_cell_outputs_attributes.present? - CellOutput.upsert_all(prev_cell_outputs_attributes, unique_by: [:tx_hash, :cell_index]) + CellOutput.upsert_all(prev_cell_outputs_attributes, + unique_by: %i[tx_hash cell_index]) end ScriptTransaction.create_from_scripts TypeScript.where(id: type_script_ids) ScriptTransaction.create_from_scripts LockScript.where(id: lock_script_ids) - return input_capacities, output_capacities + [input_capacities, output_capacities] end # def prepare_previous_outputs(inputs) @@ -905,10 +968,12 @@ def build_addresses!(outputs, local_block) # TODO use LockScript.where(script_hash: output.lock.compute_hash).select(:id)&.first replace search by code_hash, hash_type and args query after script_hash has been filled lock_script = LockScript.find_by(code_hash: item.lock.code_hash, hash_type: item.lock.hash_type, args: item.lock.args) - Address.find_or_create_address(item.lock, local_block.timestamp, lock_script.id) + Address.find_or_create_address(item.lock, local_block.timestamp, + lock_script.id) end local_cache.push("NodeData/#{block_number}/ContainedAddresses", - Address.new(id: address.id, created_at: address.created_at)) + Address.new(id: address.id, + created_at: address.created_at)) end end end @@ -963,7 +1028,7 @@ def build_scripts(outputs) end end - return locks_attributes.to_a.compact, types_attributes.to_a.compact + [locks_attributes.to_a.compact, types_attributes.to_a.compact] end def script_attributes(script, script_hash) @@ -971,7 +1036,7 @@ def script_attributes(script, script_hash) args: script.args, code_hash: script.code_hash, hash_type: script.hash_type, - script_hash: script_hash + script_hash:, } end @@ -990,7 +1055,8 @@ def build_cell_inputs( # attributes[3] is previous_cell_output type_hash # attributes[4] is previous_cell address_id # attributes[5] is previous_cell data - attributes = cell_input_attributes(item, ckb_txs[tx_index]["id"], local_block_id, prev_outputs, index) + attributes = cell_input_attributes(item, ckb_txs[tx_index]["id"], + local_block_id, prev_outputs, index) cell_inputs_attributes << attributes[:cell_input] previous_output = attributes[:previous_output] if previous_output.present? @@ -1004,7 +1070,9 @@ def build_cell_inputs( change_rec[:balance_diff] ||= 0 change_rec[:balance_diff] -= capacity change_rec[:balance_occupied_diff] ||= 0 - change_rec[:balance_occupied_diff] -= capacity if occupied?(type_hash, data) + change_rec[:balance_occupied_diff] -= capacity if occupied?( + type_hash, data + ) change_rec[:cells_diff] ||= 0 change_rec[:cells_diff] -= 1 change_rec[:ckb_txs] ||= Set.new @@ -1026,15 +1094,18 @@ def build_cell_inputs( when "udt" tags[tx_index] << "udt" udt_address_ids[tx_index] << address_id - contained_udt_ids[tx_index] << Udt.where(type_hash: type_hash, udt_type: "sudt").pick(:id) + contained_udt_ids[tx_index] << Udt.where(type_hash:, + udt_type: "sudt").pick(:id) when "omiga_inscription" tags[tx_index] << "omiga_inscription" udt_address_ids[tx_index] << address_id - contained_udt_ids[tx_index] << Udt.where(type_hash: type_hash, udt_type: "omiga_inscription").pick(:id) + contained_udt_ids[tx_index] << Udt.where(type_hash:, + udt_type: "omiga_inscription").pick(:id) when "nrc_721_token" tags[tx_index] << "nrc_721_token" udt_address_ids[tx_index] << address_id - contained_udt_ids[tx_index] << Udt.where(type_hash: type_hash, udt_type: "nrc_721_token").pick(:id) + contained_udt_ids[tx_index] << Udt.where(type_hash:, + udt_type: "nrc_721_token").pick(:id) end input_capacities[tx_index] += capacity.to_i if tx_index != 0 end @@ -1062,7 +1133,9 @@ def build_cell_outputs!( change_rec[:balance_diff] += item.capacity change_rec[:balance_occupied_diff] ||= 0 - change_rec[:balance_occupied_diff] += item.capacity if occupied?(item.type&.compute_hash, cell_data) + change_rec[:balance_occupied_diff] += item.capacity if occupied?( + item.type&.compute_hash, cell_data + ) change_rec[:cells_diff] ||= 0 change_rec[:cells_diff] += 1 @@ -1085,11 +1158,15 @@ def build_cell_outputs!( if attr[:cell_type] == "udt" tags[tx_index] << "udt" udt_address_ids[tx_index] << address.id - contained_udt_ids[tx_index] << Udt.where(type_hash: item.type.compute_hash, udt_type: "sudt").pick(:id) + contained_udt_ids[tx_index] << Udt.where( + type_hash: item.type.compute_hash, udt_type: "sudt", + ).pick(:id) elsif attr[:cell_type] == "omiga_inscription" - tags[tx_index] << "omiga_inscription" + tags[tx_index] << "omiga_inscription" udt_address_ids[tx_index] << address_id - contained_udt_ids[tx_index] << Udt.where(type_hash: item.type.compute_hash, udt_type: "omiga_inscription").pick(:id) + contained_udt_ids[tx_index] << Udt.where( + type_hash: item.type.compute_hash, udt_type: "omiga_inscription", + ).pick(:id) elsif attr[:cell_type].in?(%w(m_nft_token nrc_721_token spore_cell)) TokenTransferDetectWorker.perform_async(ckb_txs[tx_index]["id"]) end @@ -1104,15 +1181,20 @@ def occupied?(type_hash, cell_data) cell_data.present? && cell_data != "0x" || type_hash.present? end - def cell_output_attributes(output, address, ckb_transaction, local_block, cell_index, output_data) + def cell_output_attributes(output, address, ckb_transaction, local_block, +cell_index, output_data) lock_script = local_cache.fetch("NodeData/LockScript/#{output.lock.code_hash}-#{output.lock.hash_type}-#{output.lock.args}") type_script = if output.type.present? local_cache.fetch("NodeData/TypeScript/#{output.type.code_hash}-#{output.type.hash_type}-#{output.type.args}") end - udt_amount = udt_amount(cell_type(output.type, output_data), output_data, output.type&.args) + udt_amount = udt_amount(cell_type(output.type, output_data), output_data, + output.type&.args) cell_type = cell_type(output.type, output_data).to_s - update_nrc_factory_cell_info(output.type, output_data) if cell_type == "nrc_721_factory" + if cell_type == "nrc_721_factory" + update_nrc_factory_cell_info(output.type, + output_data) + end binary_data = CKB::Utils.hex_to_bin(output_data) attrs = { ckb_transaction_id: ckb_transaction["id"], @@ -1121,17 +1203,17 @@ def cell_output_attributes(output, address, ckb_transaction, local_block, cell_i address_id: address.id, block_id: local_block.id, tx_hash: ckb_transaction["tx_hash"], - cell_index: cell_index, - cell_type: cell_type, + cell_index:, + cell_type:, block_timestamp: local_block.timestamp, type_hash: output.type&.compute_hash, dao: local_block.dao, lock_script_id: lock_script.id, type_script_id: type_script&.id, - udt_amount: udt_amount, + udt_amount:, status: "live", created_at: Time.current, - updated_at: Time.current + updated_at: Time.current, } if binary_data && binary_data.bytesize > 0 @@ -1150,27 +1232,30 @@ def udt_amount(cell_type, output_data, type_script_args) case cell_type when "udt" CkbUtils.parse_udt_cell_data(output_data) + when "omiga_inscription" + CkbUtils.parse_omiga_inscription_data(output_data)[:mint_limit] when "m_nft_token" "0x#{type_script_args[-8..]}".hex end end - def cell_input_attributes(input, ckb_transaction_id, local_block_id, prev_outputs, index = nil) + def cell_input_attributes(input, ckb_transaction_id, local_block_id, +_prev_outputs, index = nil) if from_cell_base?(input) { cell_input: { - ckb_transaction_id: ckb_transaction_id, + ckb_transaction_id:, previous_tx_hash: nil, previous_index: 0, - index: index, + index:, since: input.since, block_id: local_block_id, from_cell_base: from_cell_base?(input), previous_cell_output_id: nil, cell_type: "normal", created_at: Time.current, - updated_at: Time.current - } + updated_at: Time.current, + }, } else # previous_output = prev_outputs["#{input.previous_output.tx_hash}-#{input.previous_output.index}"] @@ -1179,17 +1264,17 @@ def cell_input_attributes(input, ckb_transaction_id, local_block_id, prev_output { cell_input: { - ckb_transaction_id: ckb_transaction_id, + ckb_transaction_id:, previous_tx_hash: input.previous_output.tx_hash, previous_index: input.previous_output.index, - index: index, + index:, since: input.since, block_id: local_block_id, from_cell_base: from_cell_base?(input), previous_cell_output_id: previous_output.id, cell_type: previous_output.cell_type, created_at: Time.current, - updated_at: Time.current + updated_at: Time.current, }, previous_output: { id: previous_output.id, @@ -1200,17 +1285,18 @@ def cell_input_attributes(input, ckb_transaction_id, local_block_id, prev_output status: "dead", updated_at: Time.current, consumed_by_id: ckb_transaction_id, - consumed_block_timestamp: CkbTransaction.find(ckb_transaction_id).block_timestamp + consumed_block_timestamp: CkbTransaction.find(ckb_transaction_id).block_timestamp, }, capacity: previous_output.capacity, type_hash: previous_output.type_hash, - address_id: previous_output.address_id + address_id: previous_output.address_id, # data: previous_output.data } end end - def build_ckb_transactions!(node_block, local_block, inputs, outputs, outputs_data) + def build_ckb_transactions!(node_block, local_block, inputs, outputs, +outputs_data) cycles = CkbSync::Api.instance.get_block_cycles node_block.header.hash ckb_transactions_attributes = [] tx_index = 0 @@ -1237,25 +1323,28 @@ def build_ckb_transactions!(node_block, local_block, inputs, outputs, outputs_da # First update status thus we can use upsert later. otherwise, we may not be able to # locate correct record according to tx_hash binary_hashes = CkbUtils.hexes_to_bins_sql(hashes) - pending_txs = CkbTransaction.where("tx_hash IN (#{binary_hashes})").where(tx_status: :pending).pluck(:tx_hash, :created_at) + pending_txs = CkbTransaction.where("tx_hash IN (#{binary_hashes})").where(tx_status: :pending).pluck( + :tx_hash, :created_at + ) CkbTransaction.where("tx_hash IN (#{binary_hashes})").update_all tx_status: "committed" - txs = CkbTransaction.upsert_all(ckb_transactions_attributes, unique_by: [:tx_status, :tx_hash], + txs = CkbTransaction.upsert_all(ckb_transactions_attributes, unique_by: %i[tx_status tx_hash], returning: %w(id tx_hash block_timestamp created_at)) if pending_txs.any? hash_to_pool_times = pending_txs.to_h confirmation_time_attrs = - txs.select { |tx| + txs.select do |tx| tx["tx_hash"].tr("\\", "0").in?(hash_to_pool_times.keys) - }.map do |tx| + end.map do |tx| { id: tx["id"], tx_status: :committed, - confirmation_time: (tx["block_timestamp"].to_i / 1000) - hash_to_pool_times[tx["tx_hash"].tr("\\", "0")].to_i } + confirmation_time: (tx["block_timestamp"].to_i / 1000) - hash_to_pool_times[tx["tx_hash"].tr("\\", "0")].to_i + } end CkbTransaction.upsert_all(confirmation_time_attrs, update_only: [:confirmation_time], - unique_by: [:id, :tx_status]) + unique_by: %i[id tx_status]) end hash2id = {} @@ -1273,7 +1362,7 @@ def build_ckb_transactions!(node_block, local_block, inputs, outputs, outputs_da header_deps_attrs << { ckb_transaction_id: txid, index: i, - header_hash: dep + header_hash: dep, } end end @@ -1293,13 +1382,17 @@ def build_ckb_transactions!(node_block, local_block, inputs, outputs, outputs_da witnesses_attrs << { ckb_transaction_id: txid, index: i, - data: witness + data: witness, } end end end - Witness.upsert_all(witnesses_attrs, unique_by: %i[ckb_transaction_id index]) if witnesses_attrs.present? + if witnesses_attrs.present? + Witness.upsert_all(witnesses_attrs, + unique_by: %i[ckb_transaction_id + index]) + end txs end @@ -1318,7 +1411,7 @@ def ckb_transaction_attributes(local_block, tx, tx_index) # witnesses: tx.witnesses, is_cellbase: tx_index.zero?, live_cell_changes: live_cell_changes(tx, tx_index), - bytes: tx.serialized_size_in_block + bytes: tx.serialized_size_in_block, } end @@ -1339,10 +1432,10 @@ def build_uncle_blocks!(node_block, local_block_id) proposals: uncle_block.proposals, proposals_count: uncle_block.proposals.count, epoch: epoch_info.number, - dao: header.dao + dao: header.dao, ).find_or_create_by!( block_id: local_block_id, - block_hash: header.hash + block_hash: header.hash, ) end end @@ -1375,9 +1468,9 @@ def build_block!(node_block) proposals: node_block.proposals, proposals_count: node_block.proposals.count, cell_consumed: block_cell_consumed, - total_cell_capacity: total_cell_capacity, - miner_hash: miner_hash, - miner_lock_hash: miner_lock_hash, + total_cell_capacity:, + miner_hash:, + miner_lock_hash:, reward: base_reward, primary_reward: base_reward, secondary_reward: 0, @@ -1391,18 +1484,19 @@ def build_block!(node_block) block_size: 0, miner_message: CkbUtils.miner_message(cellbase), extension: node_block.extension, - median_timestamp: get_median_timestamp(header.hash) + median_timestamp: get_median_timestamp(header.hash), ).find_or_create_by!( block_hash: header.hash, - number: header.number + number: header.number, ) end block end def get_median_timestamp(block_hash) - response = CkbSync::Api.instance.directly_single_call_rpc method: "get_block_median_time", params: [block_hash] - return response["result"].to_i(16) + response = CkbSync::Api.instance.directly_single_call_rpc method: "get_block_median_time", + params: [block_hash] + response["result"].to_i(16) end def from_cell_base?(node_input) @@ -1437,7 +1531,7 @@ def generate_address_in_advance(cellbase, block_timestamp) lock = LockScript.find_or_create_by( code_hash: lock_script.code_hash, hash_type: lock_script.hash_type, - args: lock_script.args + args: lock_script.args, ) local_cache.fetch("NodeData/Address/#{lock_script.code_hash}-#{lock_script.hash_type}-#{lock_script.args}") do Address.find_or_create_address(lock_script, block_timestamp, lock.id) @@ -1469,14 +1563,14 @@ def update_nrc_factory_cell_info(type_script, output_data) factory_cell = NrcFactoryCell.find_or_create_by( code_hash: type_script.code_hash, hash_type: type_script.hash_type, - args: type_script.args + args: type_script.args, ) parsed_factory_data = CkbUtils.parse_nrc_721_factory_data(output_data) factory_cell.update( name: parsed_factory_data.name, symbol: parsed_factory_data.symbol, base_token_uri: parsed_factory_data.base_token_uri, - extra_data: parsed_factory_data.extra_data + extra_data: parsed_factory_data.extra_data, ) end diff --git a/app/utils/ckb_utils.rb b/app/utils/ckb_utils.rb index e4687e8b1..e54c92782 100644 --- a/app/utils/ckb_utils.rb +++ b/app/utils/ckb_utils.rb @@ -447,8 +447,6 @@ def self.cell_type(type_script, output_data) "spore_cell" when CkbSync::Api.instance.omiga_inscription_info_code_hash "omiga_inscription_info" - when CkbSync::Api.instance.omiga_inscription_info_code_hash - "omiga_inscription_info" when CkbSync::Api.instance.xudt_code_hash if OmigaInscriptionInfo.where(udt_hash: type_script.compute_hash).exists? "omiga_inscription" @@ -639,4 +637,10 @@ def self.parse_omiga_inscription_info(hex_data) { decimal:, name: name.presence, symbol: symbol.presence, udt_hash:, expected_supply:, mint_limit:, mint_status: } end + + def self.parse_omiga_inscription_data(hex_data) + data = hex_data.delete_prefix("0x") + mint_limit = [data].pack("H*").unpack1("Q<2") + { mint_limit: } + end end diff --git a/test/models/ckb_sync/node_data_processor_test.rb b/test/models/ckb_sync/node_data_processor_test.rb index 33c81f32a..8726562dc 100644 --- a/test/models/ckb_sync/node_data_processor_test.rb +++ b/test/models/ckb_sync/node_data_processor_test.rb @@ -8,13 +8,13 @@ class NodeDataProcessorTest < ActiveSupport::TestCase compact_target: "0x1000", length: "0x07d0", number: "0x0", - start_number: "0x0" - ) + start_number: "0x0", + ), ) CkbSync::Api.any_instance.stubs(:get_block_cycles).returns( [ "0x100", "0x200", "0x300", "0x400", "0x500", "0x600", "0x700", "0x800", "0x900" - ] + ], ) create(:table_record_count, :block_counter) create(:table_record_count, :ckb_transactions_counter) @@ -59,7 +59,9 @@ class NodeDataProcessorTest < ActiveSupport::TestCase VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}") do node_block = CkbSync::Api.instance.get_block_by_number(DEFAULT_NODE_BLOCK_NUMBER) create(:block, :with_block_hash, number: node_block.header.number - 1) - assert_difference -> { ckb_transaction_counter.reload.count }, node_block.transactions[1..-1].count do + assert_difference -> { + ckb_transaction_counter.reload.count + }, node_block.transactions[1..-1].count do node_data_processor.process_block(node_block) end end @@ -71,8 +73,8 @@ class NodeDataProcessorTest < ActiveSupport::TestCase compact_target: "0x1000", length: "0x3e8", number: "0x0", - start_number: "0x0" - ) + start_number: "0x0", + ), ) VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}") do node_block = CkbSync::Api.instance.get_block_by_number(DEFAULT_NODE_BLOCK_NUMBER) @@ -119,8 +121,8 @@ class NodeDataProcessorTest < ActiveSupport::TestCase compact_target: "0x1000", length: "0x07d0", number: "0x0", - start_number: "0x0" - ) + start_number: "0x0", + ), ) VCR.use_cassette("blocks/11") do node_block = CkbSync::Api.instance.get_block_by_number(11) @@ -140,18 +142,22 @@ class NodeDataProcessorTest < ActiveSupport::TestCase compact_target: "0x1000", length: "0x07d0", number: "0x0", - start_number: "0x0" - ) + start_number: "0x0", + ), ) VCR.use_cassette("blocks/11") do - tx = create(:pending_transaction, tx_hash: "0x4298daf91148df9093c844d2ae7d16bee6b74e7ab1ccccd108ce834d1ca1a56c") + tx = create(:pending_transaction, + tx_hash: "0x4298daf91148df9093c844d2ae7d16bee6b74e7ab1ccccd108ce834d1ca1a56c") node_block = CkbSync::Api.instance.get_block_by_number(11) create(:block, :with_block_hash, number: node_block.header.number - 1) node_block.transactions.first.hash = tx.tx_hash - assert_changes -> { tx.reload.tx_status }, from: "pending", to: "committed" do + assert_changes -> { + tx.reload.tx_status + }, from: "pending", to: "committed" do node_data_processor.process_block(node_block) end - assert_equal tx.reload.confirmation_time, tx.reload.block_timestamp.to_i / 1000 - tx.created_at.to_i + assert_equal tx.reload.confirmation_time, + tx.reload.block_timestamp.to_i / 1000 - tx.created_at.to_i end end @@ -161,8 +167,8 @@ class NodeDataProcessorTest < ActiveSupport::TestCase compact_target: "0x1000", length: "0x07d0", number: "0x0", - start_number: "0x0" - ) + start_number: "0x0", + ), ) VCR.use_cassette("blocks/11") do tx = create(:pending_transaction) @@ -180,8 +186,8 @@ class NodeDataProcessorTest < ActiveSupport::TestCase compact_target: "0x1000", length: "0x07d0", number: "0x0", - start_number: "0x0" - ) + start_number: "0x0", + ), ) VCR.use_cassette("blocks/11") do node_block = CkbSync::Api.instance.get_block_by_number(11) @@ -194,7 +200,8 @@ class NodeDataProcessorTest < ActiveSupport::TestCase end test "#process_block generated block's total_cell_capacity should equal to the sum of transactions output capacity" do - VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", record: :new_episodes) do + VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", + record: :new_episodes) do node_block = CkbSync::Api.instance.get_block_by_number(DEFAULT_NODE_BLOCK_NUMBER) create(:block, :with_block_hash, number: node_block.header.number - 1) @@ -212,7 +219,8 @@ class NodeDataProcessorTest < ActiveSupport::TestCase node_block.transactions.first local_block = node_data_processor.process_block(node_block) - assert_equal CkbUtils.base_reward(node_block.header.number, CkbUtils.parse_epoch_info(node_block.header).number), local_block.reward + assert_equal CkbUtils.base_reward(node_block.header.number, CkbUtils.parse_epoch_info(node_block.header).number), + local_block.reward end end @@ -223,12 +231,14 @@ class NodeDataProcessorTest < ActiveSupport::TestCase local_block = node_data_processor.process_block(node_block) - assert_equal CkbUtils.base_reward(node_block.header.number, CkbUtils.parse_epoch_info(node_block.header).number), local_block.primary_reward + assert_equal CkbUtils.base_reward(node_block.header.number, CkbUtils.parse_epoch_info(node_block.header).number), + local_block.primary_reward end end test "#process_block generated block should has correct secondary reward" do - VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", record: :new_episodes) do + VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", + record: :new_episodes) do node_block = CkbSync::Api.instance.get_block_by_number(DEFAULT_NODE_BLOCK_NUMBER) create(:block, :with_block_hash, number: node_block.header.number - 1) @@ -245,7 +255,8 @@ class NodeDataProcessorTest < ActiveSupport::TestCase local_block = node_data_processor.process_block(node_block) - assert_equal CkbUtils.block_cell_consumed(node_block.transactions), local_block.cell_consumed + assert_equal CkbUtils.block_cell_consumed(node_block.transactions), + local_block.cell_consumed end end @@ -255,7 +266,9 @@ class NodeDataProcessorTest < ActiveSupport::TestCase create(:block, :with_block_hash, number: node_block.header.number - 1) node_block_uncle_blocks = node_block.uncles - assert_difference -> { UncleBlock.count }, node_block_uncle_blocks.size do + assert_difference -> { + UncleBlock.count + }, node_block_uncle_blocks.size do node_data_processor.process_block(node_block) end end @@ -265,8 +278,12 @@ class NodeDataProcessorTest < ActiveSupport::TestCase VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}") do node_block = CkbSync::Api.instance.get_block_by_number(DEFAULT_NODE_BLOCK_NUMBER) create(:block, :with_block_hash, number: node_block.header.number - 1) - node_uncle_blocks = node_block.uncles.map { |uncle| uncle.to_h.deep_stringify_keys } - formatted_node_uncle_blocks = node_uncle_blocks.map { |uncle_block| format_node_block(uncle_block).sort } + node_uncle_blocks = node_block.uncles.map do |uncle| + uncle.to_h.deep_stringify_keys + end + formatted_node_uncle_blocks = node_uncle_blocks.map do |uncle_block| + format_node_block(uncle_block).sort + end local_block = node_data_processor.process_block(node_block) local_uncle_blocks = @@ -291,7 +308,9 @@ class NodeDataProcessorTest < ActiveSupport::TestCase node_block = CkbSync::Api.instance.get_block_by_number(DEFAULT_NODE_BLOCK_NUMBER) create(:block, :with_block_hash, number: node_block.header.number - 1) node_uncle_blocks = node_block.uncles - node_uncle_blocks_count = node_uncle_blocks.reduce(0) { |memo, uncle_block| memo + uncle_block.proposals.size } + node_uncle_blocks_count = node_uncle_blocks.reduce(0) do |memo, uncle_block| + memo + uncle_block.proposals.size + end local_block = node_data_processor.process_block(node_block) local_uncle_blocks = local_block.uncle_blocks @@ -310,7 +329,9 @@ class NodeDataProcessorTest < ActiveSupport::TestCase create(:block, :with_block_hash, number: node_block.header.number - 1) node_block_transactions = node_block.transactions - assert_difference -> { CkbTransaction.count }, node_block_transactions.count do + assert_difference -> { + CkbTransaction.count + }, node_block_transactions.count do node_data_processor.process_block(node_block) end end @@ -323,7 +344,8 @@ class NodeDataProcessorTest < ActiveSupport::TestCase local_block = node_data_processor.process_block(node_block) - assert_equal node_block.transactions.size, local_block.ckb_transactions_count + assert_equal node_block.transactions.size, + local_block.ckb_transactions_count end end @@ -342,7 +364,8 @@ class NodeDataProcessorTest < ActiveSupport::TestCase local_block.ckb_transactions.map do |ckb_transaction| attrs = ckb_transaction.attributes.select do |attribute| - attribute.in?(%w(tx_hash cell_deps header_deps version witnesses)) + attribute.in?(%w(tx_hash cell_deps header_deps version + witnesses)) end attrs["hash"] = attrs.delete("tx_hash") attrs["version"] = attrs["version"].to_i @@ -361,13 +384,13 @@ class NodeDataProcessorTest < ActiveSupport::TestCase create(:block, :with_block_hash, number: node_block.header.number - 1) block = create(:block, :with_block_hash) ckb_transaction1 = create(:ckb_transaction, - tx_hash: "0x498315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block: block) + tx_hash: "0x498315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block:) ckb_transaction2 = create(:ckb_transaction, - tx_hash: "0x598315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block: block) + tx_hash: "0x598315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block:) create(:cell_output, ckb_transaction: ckb_transaction1, cell_index: 1, - tx_hash: "0x498315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block: block, capacity: 4 * 10**8) + tx_hash: "0x498315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block:, capacity: 4 * 10**8) create(:cell_output, ckb_transaction: ckb_transaction2, cell_index: 2, - tx_hash: "0x598315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block: block) + tx_hash: "0x598315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block:) node_block_transactions = node_block.transactions local_block = node_data_processor.process_block(node_block) @@ -375,7 +398,8 @@ class NodeDataProcessorTest < ActiveSupport::TestCase node_block_transactions.each_with_index.map do |transaction, index| index.zero? ? 1 : transaction.outputs.count - transaction.inputs.count end - assert_equal expected_live_cell_changes, local_block.ckb_transactions.order(:id).map(&:live_cell_changes) + assert_equal expected_live_cell_changes, + local_block.ckb_transactions.order(:id).map(&:live_cell_changes) end end @@ -385,13 +409,13 @@ class NodeDataProcessorTest < ActiveSupport::TestCase create(:block, :with_block_hash, number: node_block.header.number - 1) block = create(:block, :with_block_hash) ckb_transaction1 = create(:ckb_transaction, - tx_hash: "0x498315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block: block) + tx_hash: "0x498315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block:) ckb_transaction2 = create(:ckb_transaction, - tx_hash: "0x598315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block: block) + tx_hash: "0x598315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block:) create(:cell_output, ckb_transaction: ckb_transaction1, cell_index: 1, - tx_hash: "0x498315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block: block) + tx_hash: "0x498315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block:) create(:cell_output, ckb_transaction: ckb_transaction2, cell_index: 2, - tx_hash: "0x598315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block: block) + tx_hash: "0x598315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block:) local_block = node_data_processor.process_block(node_block) expected_capacity_involved = local_block.ckb_transactions.normal.map(&:capacity_involved) @@ -407,16 +431,17 @@ class NodeDataProcessorTest < ActiveSupport::TestCase create(:block, :with_block_hash, number: node_block.header.number - 1) block = create(:block, :with_block_hash) ckb_transaction1 = create(:ckb_transaction, - tx_hash: "0x498315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block: block) + tx_hash: "0x498315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block:) ckb_transaction2 = create(:ckb_transaction, - tx_hash: "0x598315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block: block) + tx_hash: "0x598315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block:) create(:cell_output, ckb_transaction: ckb_transaction1, cell_index: 1, - tx_hash: "0x498315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block: block, capacity: 4 * 10**8) + tx_hash: "0x498315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block:, capacity: 4 * 10**8) create(:cell_output, ckb_transaction: ckb_transaction2, cell_index: 2, - tx_hash: "0x598315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block: block) + tx_hash: "0x598315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block:) local_block = node_data_processor.process_block(node_block) - assert_equal local_block.live_cell_changes, local_block.ckb_transactions.sum(&:live_cell_changes) + assert_equal local_block.live_cell_changes, + local_block.ckb_transactions.sum(&:live_cell_changes) end end @@ -441,27 +466,27 @@ class NodeDataProcessorTest < ActiveSupport::TestCase node_block = CkbSync::Api.instance.get_block_by_number(DEFAULT_NODE_BLOCK_NUMBER) create(:block, :with_block_hash, number: node_block.header.number - 1) node_transactions = node_block.transactions.map(&:to_h).map(&:deep_stringify_keys) - node_block_cell_inputs = node_transactions.map { |commit_transaction| + node_block_cell_inputs = node_transactions.map do |commit_transaction| commit_transaction["inputs"].map do |input| { "previous_tx_hash" => input["previous_output"]["tx_hash"] == CellOutput::SYSTEM_TX_HASH ? nil : input["previous_output"]["tx_hash"], "index" => input["previous_output"]["tx_hash"] == CellOutput::SYSTEM_TX_HASH ? 0 : input["previous_output"]["index"].hex, - "since" => input["since"].hex + "since" => input["since"].hex, } end - }.flatten + end.flatten local_block = node_data_processor.process_block(node_block) local_block_transactions = local_block.ckb_transactions - local_block_cell_inputs = local_block_transactions.map { |commit_transaction| + local_block_cell_inputs = local_block_transactions.map do |commit_transaction| commit_transaction.cell_inputs.map do |cell_input| { "previous_tx_hash" => cell_input.previous_tx_hash, "index" => cell_input.previous_index, - "since" => cell_input.since + "since" => cell_input.since, } end - }.flatten + end.flatten # binding.pry assert_equal node_block_cell_inputs, local_block_cell_inputs end @@ -488,21 +513,21 @@ class NodeDataProcessorTest < ActiveSupport::TestCase node_block = CkbSync::Api.instance.get_block_by_number(DEFAULT_NODE_BLOCK_NUMBER) create(:block, :with_block_hash, number: node_block.header.number - 1) node_block_transactions = node_block.transactions - node_block_cell_outputs = node_block_transactions.map { |commit_transaction| + node_block_cell_outputs = node_block_transactions.map do |commit_transaction| commit_transaction.to_h.deep_stringify_keys["outputs"].map do |output| format_node_block_cell_output(output).sort end - }.flatten + end.flatten local_block = node_data_processor.process_block(node_block) local_block_transactions = local_block.ckb_transactions - local_block_cell_outputs = local_block_transactions.map { |commit_transaction| + local_block_cell_outputs = local_block_transactions.map do |commit_transaction| commit_transaction.cell_outputs.map do |cell_output| attributes = cell_output.attributes attributes["capacity"] = attributes["capacity"] attributes.select { |attribute| attribute == "capacity" }.sort end - }.flatten + end.flatten assert_equal node_block_cell_outputs, local_block_cell_outputs end @@ -520,7 +545,8 @@ class NodeDataProcessorTest < ActiveSupport::TestCase local_block = node_data_processor.process_block(node_block) cell = local_block.cell_outputs.order(:id).first - assert_equal "0x3307186493c5da8b91917924253a5ffd35231151649d0c7e2941aa8801815063", cell.data + assert_equal "0x3307186493c5da8b91917924253a5ffd35231151649d0c7e2941aa8801815063", + cell.data end end @@ -541,10 +567,12 @@ class NodeDataProcessorTest < ActiveSupport::TestCase node_output = node_block.transactions.first.outputs.first node_output.type = CKB::Types::Script.new(code_hash: Settings.dao_code_hash, args: "0xb2e61ff569acf041b3c2c17724e2379c581eeac3", hash_type: "type") - node_block.transactions.first.outputs_data[0] = CKB::Utils.bin_to_hex("\x00" * 8) + node_block.transactions.first.outputs_data[0] = + CKB::Utils.bin_to_hex("\x00" * 8) local_block = node_data_processor.process_block(node_block) - assert_equal ["nervos_dao_deposit"], local_block.cell_outputs.pluck(:cell_type).uniq + assert_equal ["nervos_dao_deposit"], + local_block.cell_outputs.pluck(:cell_type).uniq end end @@ -555,10 +583,12 @@ class NodeDataProcessorTest < ActiveSupport::TestCase node_output = node_block.transactions.first.outputs.first node_output.type = CKB::Types::Script.new(code_hash: Settings.dao_type_hash, args: "0xb2e61ff569acf041b3c2c17724e2379c581eeac3", hash_type: "type") - node_block.transactions.first.outputs_data[0] = CKB::Utils.bin_to_hex("\x00" * 8) + node_block.transactions.first.outputs_data[0] = + CKB::Utils.bin_to_hex("\x00" * 8) local_block = node_data_processor.process_block(node_block) - assert_equal ["nervos_dao_deposit"], local_block.cell_outputs.pluck(:cell_type).uniq + assert_equal ["nervos_dao_deposit"], + local_block.cell_outputs.pluck(:cell_type).uniq end end @@ -569,10 +599,12 @@ class NodeDataProcessorTest < ActiveSupport::TestCase node_output = node_block.transactions.first.outputs.first node_output.type = CKB::Types::Script.new(code_hash: Settings.dao_type_hash, args: "0xb2e61ff569acf041b3c2c17724e2379c581eeac3", hash_type: "type") - node_block.transactions.first.outputs_data[0] = CKB::Utils.bin_to_hex("\x02" * 8) + node_block.transactions.first.outputs_data[0] = + CKB::Utils.bin_to_hex("\x02" * 8) local_block = node_data_processor.process_block(node_block) - assert_equal ["nervos_dao_withdrawing"], local_block.cell_outputs.pluck(:cell_type).uniq + assert_equal ["nervos_dao_withdrawing"], + local_block.cell_outputs.pluck(:cell_type).uniq end end @@ -582,19 +614,25 @@ class NodeDataProcessorTest < ActiveSupport::TestCase create(:block, :with_block_hash, number: node_block.header.number - 1) locks = node_block.transactions.map(&:outputs).flatten.map(&:lock) local_block = node_data_processor.process_block(node_block) - expected_lock_address = locks.map { |lock| Address.find_or_create_address(lock, node_block.header.timestamp) } + expected_lock_address = locks.map do |lock| + Address.find_or_create_address(lock, node_block.header.timestamp) + end - assert_equal expected_lock_address, local_block.cell_outputs.map(&:address) + assert_equal expected_lock_address, + local_block.cell_outputs.map(&:address) end end test "#process_block should create addresses for ckb transaction" do - VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", record: :new_episodes) do + VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", + record: :new_episodes) do node_block = CkbSync::Api.instance.get_block_by_number(DEFAULT_NODE_BLOCK_NUMBER) create(:block, :with_block_hash, number: node_block.header.number - 1) locks = node_block.transactions.map(&:outputs).flatten.map(&:lock) local_block = node_data_processor.process_block(node_block) - expected_lock_address = locks.map { |lock| Address.find_or_create_address(lock, node_block.header.timestamp) } + expected_lock_address = locks.map do |lock| + Address.find_or_create_address(lock, node_block.header.timestamp) + end assert_equal expected_lock_address, Address.where(id: local_block.ckb_transactions.map(&:contained_address_ids).flatten) @@ -607,10 +645,10 @@ class NodeDataProcessorTest < ActiveSupport::TestCase create(:block, :with_block_hash, number: node_block.header.number - 1) expected_lock_scripts = node_block.transactions.map(&:outputs).flatten.map(&:lock).map(&:to_h) local_block = node_data_processor.process_block(node_block) - actual_lock_scripts = local_block.cell_outputs.map { |cell_output| + actual_lock_scripts = local_block.cell_outputs.map do |cell_output| CKB::Types::Script.new(code_hash: cell_output.lock_script.code_hash, args: cell_output.lock_script.args, hash_type: "type") - }.map(&:to_h) + end.map(&:to_h) assert_equal expected_lock_scripts, actual_lock_scripts end @@ -621,21 +659,21 @@ class NodeDataProcessorTest < ActiveSupport::TestCase node_block = CkbSync::Api.instance.get_block_by_number(DEFAULT_NODE_BLOCK_NUMBER) create(:block, :with_block_hash, number: node_block.header.number - 1) node_block_transactions = node_block.transactions - node_block_lock_scripts = node_block_transactions.map { |commit_transaction| - commit_transaction.to_h.deep_stringify_keys["outputs"].map { |output| + node_block_lock_scripts = node_block_transactions.map do |commit_transaction| + commit_transaction.to_h.deep_stringify_keys["outputs"].map do |output| output["lock"] - }.sort - }.flatten + end.sort + end.flatten local_block = node_data_processor.process_block(node_block) local_block_transactions = local_block.ckb_transactions - local_block_lock_scripts = local_block_transactions.map { |commit_transaction| - commit_transaction.cell_outputs.map { |cell_output| + local_block_lock_scripts = local_block_transactions.map do |commit_transaction| + commit_transaction.cell_outputs.map do |cell_output| cell_output.lock_script.attributes.select do |attribute| attribute.in?(%w(args code_hash hash_type)) end - }.sort - }.flatten + end.sort + end.flatten assert_equal node_block_lock_scripts, local_block_lock_scripts end @@ -647,9 +685,13 @@ class NodeDataProcessorTest < ActiveSupport::TestCase create(:block, :with_block_hash, number: node_block.header.number - 1) node_block_transactions = node_block.transactions node_cell_outputs = node_block_transactions.map(&:outputs).flatten - node_cell_outputs_with_type_script = node_cell_outputs.select { |cell_output| cell_output.type.present? } + node_cell_outputs_with_type_script = node_cell_outputs.select do |cell_output| + cell_output.type.present? + end - assert_difference -> { TypeScript.count }, node_cell_outputs_with_type_script.size do + assert_difference -> { + TypeScript.count + }, node_cell_outputs_with_type_script.size do node_data_processor.process_block(node_block) end end @@ -661,21 +703,21 @@ class NodeDataProcessorTest < ActiveSupport::TestCase create(:block, :with_block_hash, number: node_block.header.number - 1) fake_node_block_with_type_script(node_block) node_block_transactions = node_block.transactions - node_block_type_scripts = node_block_transactions.map { |commit_transaction| - commit_transaction.to_h.deep_stringify_keys["outputs"].map { |output| + node_block_type_scripts = node_block_transactions.map do |commit_transaction| + commit_transaction.to_h.deep_stringify_keys["outputs"].map do |output| output["type"] - }.sort - }.flatten + end.sort + end.flatten local_block = node_data_processor.process_block(node_block) local_block_transactions = local_block.ckb_transactions - local_block_type_scripts = local_block_transactions.map { |commit_transaction| - commit_transaction.cell_outputs.map { |cell_output| + local_block_type_scripts = local_block_transactions.map do |commit_transaction| + commit_transaction.cell_outputs.map do |cell_output| cell_output.type_script.attributes.select do |attribute| attribute.in?(%w(args code_hash hash_type)) end - }.sort - }.flatten + end.sort + end.flatten assert_equal node_block_type_scripts, local_block_type_scripts end @@ -684,17 +726,18 @@ class NodeDataProcessorTest < ActiveSupport::TestCase test "#process_block should update block's total transaction fee" do node_block = fake_node_block("0x3307186493c5da8b91917924253a5ffd35231151649d0c7e2941aa8801815063") create(:block, :with_block_hash, number: node_block.header.number - 1) - VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", record: :new_episodes) do + VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", + record: :new_episodes) do block = create(:block, :with_block_hash) ckb_transaction1 = create(:ckb_transaction, - tx_hash: "0x498315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block: block) + tx_hash: "0x498315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block:) ckb_transaction2 = create(:ckb_transaction, - tx_hash: "0x598315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block: block) + tx_hash: "0x598315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block:) lock = create(:lock_script) create(:cell_output, ckb_transaction: ckb_transaction1, cell_index: 1, - tx_hash: "0x498315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block: block, lock_script_id: lock.id) + tx_hash: "0x498315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block:, lock_script_id: lock.id) create(:cell_output, ckb_transaction: ckb_transaction2, cell_index: 2, - tx_hash: "0x598315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block: block, lock_script_id: lock.id) + tx_hash: "0x598315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block:, lock_script_id: lock.id) local_block = node_data_processor.process_block(node_block) assert_equal 10**8 * 5, local_block.reload.total_transaction_fee @@ -704,24 +747,28 @@ class NodeDataProcessorTest < ActiveSupport::TestCase test "#process_block should update block's contained addresses's transactions count even if fee is a negative number" do node_block = fake_node_block("0x3307186493c5da8b91917924253a5ffd35231151649d0c7e2941aa8801815063") create(:block, :with_block_hash, number: node_block.header.number - 1) - VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", record: :new_episodes) do + VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", + record: :new_episodes) do block = create(:block, :with_block_hash) lock = node_block.transactions.last.outputs.first.lock - lock_script = create(:lock_script, code_hash: lock.code_hash, hash_type: lock.hash_type, args: lock.args) - addr = Address.find_or_create_address(lock, node_block.header.timestamp, lock_script.id) + lock_script = create(:lock_script, code_hash: lock.code_hash, + hash_type: lock.hash_type, args: lock.args) + addr = Address.find_or_create_address(lock, + node_block.header.timestamp, lock_script.id) ckb_transaction1 = create(:ckb_transaction, - tx_hash: "0x498315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block: block, contained_address_ids: [addr.id]) + tx_hash: "0x498315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block:, contained_address_ids: [addr.id]) ckb_transaction2 = create(:ckb_transaction, - tx_hash: "0x598315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block: block, contained_address_ids: [addr.id]) + tx_hash: "0x598315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block:, contained_address_ids: [addr.id]) addr.update(ckb_transactions_count: 2) create(:cell_output, ckb_transaction: ckb_transaction1, cell_index: 1, - tx_hash: "0x498315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block: block, capacity: 4 * 10**8, address: addr) + tx_hash: "0x498315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block:, capacity: 4 * 10**8, address: addr) create(:cell_output, ckb_transaction: ckb_transaction2, cell_index: 2, - tx_hash: "0x598315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block: block, address: addr) + tx_hash: "0x598315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block:, address: addr) local_block = node_data_processor.process_block(node_block) - assert_equal 5, local_block.contained_addresses.map(&:ckb_transactions_count).flatten.sum + assert_equal 5, + local_block.contained_addresses.map(&:ckb_transactions_count).flatten.sum end end @@ -731,26 +778,31 @@ class NodeDataProcessorTest < ActiveSupport::TestCase create(:block, :with_block_hash, number: node_block.header.number - 1) VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}") do lock = node_block.transactions.last.outputs.first.lock - lock_script = create(:lock_script, code_hash: lock.code_hash, hash_type: lock.hash_type, args: lock.args) - addr = Address.find_or_create_address(lock, node_block.header.timestamp, lock_script.id) + lock_script = create(:lock_script, code_hash: lock.code_hash, + hash_type: lock.hash_type, args: lock.args) + addr = Address.find_or_create_address(lock, + node_block.header.timestamp, lock_script.id) fake_dao_deposit_transaction(node_block) local_block = node_data_processor.process_block(node_block) - assert_equal 5, local_block.contained_addresses.map(&:ckb_transactions_count).flatten.sum + assert_equal 5, + local_block.contained_addresses.map(&:ckb_transactions_count).flatten.sum end end test "should create forked event when block is invalid " do node_block = fake_node_block - create(:block, :with_block_hash, number: node_block.header.number - 1, timestamp: 1557282351075) + create(:block, :with_block_hash, number: node_block.header.number - 1, + timestamp: 1557282351075) VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}") do fake_dao_deposit_transaction(node_block) node_data_processor.process_block(node_block) end local_block = Block.find_by(number: DEFAULT_NODE_BLOCK_NUMBER) local_block.update(block_hash: "0x419c632366c8eb9635acbb39ea085f7552ae62e1fdd480893375334a0f37d1bx") - VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", record: :new_episodes) do + VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", + record: :new_episodes) do assert_difference -> { ForkedEvent.count }, 1 do node_data_processor.call end @@ -761,7 +813,8 @@ class NodeDataProcessorTest < ActiveSupport::TestCase test "should revert dao contract total depositors count when block is invalid and there is dao cell" do CkbSync::Api.any_instance.stubs(:calculate_dao_maximum_withdraw).returns("0x2faf0be8") node_block = fake_node_block - create(:block, :with_block_hash, number: node_block.header.number - 1, timestamp: 1557282351075) + create(:block, :with_block_hash, number: node_block.header.number - 1, + timestamp: 1557282351075) VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}") do fake_dao_deposit_transaction(node_block) node_data_processor.process_block(node_block) @@ -770,8 +823,11 @@ class NodeDataProcessorTest < ActiveSupport::TestCase local_block = Block.find_by(number: DEFAULT_NODE_BLOCK_NUMBER) local_block.update(block_hash: "0x419c632366c8eb9635acbb39ea085f7552ae62e1fdd480893375334a0f37d1bx") - VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", record: :new_episodes) do - assert_difference -> { dao_contract.reload.total_depositors_count }, -1 do + VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", + record: :new_episodes) do + assert_difference -> { + dao_contract.reload.total_depositors_count + }, -1 do node_data_processor.call end @@ -781,18 +837,19 @@ class NodeDataProcessorTest < ActiveSupport::TestCase end test "#process_block should update cell status" do - VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", record: :new_episodes) do + VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", + record: :new_episodes) do node_block = fake_node_block("0x3307186493c5da8b91917924253a5ffd35231151649d0c7e2941aa8801815063") create(:block, :with_block_hash, number: node_block.header.number - 1) block = create(:block, :with_block_hash) ckb_transaction1 = create(:ckb_transaction, - tx_hash: "0x498315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block: block) + tx_hash: "0x498315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block:) ckb_transaction2 = create(:ckb_transaction, - tx_hash: "0x598315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block: block) + tx_hash: "0x598315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block:) create(:cell_output, ckb_transaction: ckb_transaction1, cell_index: 1, - tx_hash: "0x498315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block: block) + tx_hash: "0x498315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block:) create(:cell_output, ckb_transaction: ckb_transaction2, cell_index: 2, - tx_hash: "0x598315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block: block) + tx_hash: "0x598315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block:) assert_difference -> { CellOutput.dead.count }, 2 do node_data_processor.process_block(node_block) @@ -809,17 +866,18 @@ class NodeDataProcessorTest < ActiveSupport::TestCase node_block = fake_node_block("0x3307186493c5da8b91917924253a5ffd35231151649d0c7e2941aa8801815063") block = create(:block, :with_block_hash) ckb_transaction1 = create(:ckb_transaction, - tx_hash: "0x498315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block: block) + tx_hash: "0x498315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block:) ckb_transaction2 = create(:ckb_transaction, - tx_hash: "0x598315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block: block) + tx_hash: "0x598315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block:) create(:cell_output, ckb_transaction: ckb_transaction1, cell_index: 1, - tx_hash: "0x498315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block: block) + tx_hash: "0x498315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block:) create(:cell_output, ckb_transaction: ckb_transaction2, cell_index: 2, - tx_hash: "0x598315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block: block) + tx_hash: "0x598315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block:) create(:block, :with_block_hash, number: node_block.header.number - 1) local_block = node_data_processor.process_block(node_block) - assert_empty local_block.cell_inputs.where(from_cell_base: false, previous_cell_output_id: nil) + assert_empty local_block.cell_inputs.where(from_cell_base: false, + previous_cell_output_id: nil) end end @@ -829,12 +887,15 @@ class NodeDataProcessorTest < ActiveSupport::TestCase node_block = CkbSync::Api.instance.get_block_by_number(25) cellbase = node_block.transactions.first lock_script = CkbUtils.generate_lock_script_from_cellbase(cellbase) - miner_address = Address.find_or_create_address(lock_script, node_block.header.timestamp) + miner_address = Address.find_or_create_address(lock_script, + node_block.header.timestamp) assert_difference -> { MiningInfo.count }, 1 do node_data_processor.process_block(node_block) end - assert_equal "mined", MiningInfo.find_by(block_number: 25, address_id: miner_address.id).status + assert_equal "mined", + MiningInfo.find_by(block_number: 25, + address_id: miner_address.id).status end end @@ -844,7 +905,9 @@ class NodeDataProcessorTest < ActiveSupport::TestCase local_block.update(block_hash: "0x419c632366c8eb9635acbb39ea085f7552ae62e1fdd480893375334a0f37d1bx") VCR.use_cassette("blocks/25") do - assert_changes -> { MiningInfo.find_by(block_number: 24).status }, from: "mined", to: "reverted" do + assert_changes -> { + MiningInfo.find_by(block_number: 24).status + }, from: "mined", to: "reverted" do node_data_processor.call end end @@ -858,7 +921,9 @@ class NodeDataProcessorTest < ActiveSupport::TestCase local_block.target_block.update(miner_hash: addr.address_hash) VCR.use_cassette("blocks/25") do - assert_difference -> { local_block.miner_address.reload.mined_blocks_count }, -1 do + assert_difference -> { + local_block.miner_address.reload.mined_blocks_count + }, -1 do node_data_processor.call end end @@ -870,7 +935,8 @@ class NodeDataProcessorTest < ActiveSupport::TestCase node_block = CkbSync::Api.instance.get_block_by_number(25) cellbase = node_block.transactions.first lock_script = CkbUtils.generate_lock_script_from_cellbase(cellbase) - miner_address = Address.find_or_create_address(lock_script, node_block.header.timestamp) + miner_address = Address.find_or_create_address(lock_script, + node_block.header.timestamp) assert_difference -> { miner_address.reload.mined_blocks_count }, 1 do node_data_processor.process_block(node_block) @@ -884,7 +950,9 @@ class NodeDataProcessorTest < ActiveSupport::TestCase local_block.update(block_hash: "0x419c632366c8eb9635acbb39ea085f7552ae62e1fdd480893375334a0f37d1bx") VCR.use_cassette("blocks/13") do - assert_difference -> { local_block.contained_addresses.map(&:ckb_transactions_count).flatten.sum }, -1 do + assert_difference -> { + local_block.contained_addresses.map(&:ckb_transactions_count).flatten.sum + }, -1 do node_data_processor.call end end @@ -911,7 +979,9 @@ class NodeDataProcessorTest < ActiveSupport::TestCase local_block.update(block_hash: "0x419c632366c8eb9635acbb39ea085f7552ae62e1fdd480893375334a0f37d1bx") VCR.use_cassette("blocks/13") do - assert_difference -> { ckb_transactions_counter.reload.count }, -local_block.ckb_transactions.normal.count do + assert_difference -> { + ckb_transactions_counter.reload.count + }, -local_block.ckb_transactions.normal.count do node_data_processor.call end end @@ -927,7 +997,8 @@ class NodeDataProcessorTest < ActiveSupport::TestCase VCR.use_cassette("blocks/12", record: :new_episodes) do new_local_block = node_data_processor.call - assert_equal origin_balance - balance_diff, new_local_block.contained_addresses.sum(:balance) + assert_equal origin_balance - balance_diff, + new_local_block.contained_addresses.sum(:balance) end end @@ -938,11 +1009,14 @@ class NodeDataProcessorTest < ActiveSupport::TestCase VCR.use_cassette("blocks/13", record: :new_episodes) do new_local_block = node_data_processor.call - assert_equal origin_live_cells_count + 1, new_local_block.contained_addresses.sum(:live_cells_count) + assert_equal origin_live_cells_count + 1, + new_local_block.contained_addresses.sum(:live_cells_count) address = new_local_block.contained_addresses.first - snapshot = AddressBlockSnapshot.find_by(block_id: new_local_block.id, address_id: address.id) - assert_equal snapshot.final_state["live_cells_count"], address.live_cells_count + snapshot = AddressBlockSnapshot.find_by(block_id: new_local_block.id, + address_id: address.id) + assert_equal snapshot.final_state["live_cells_count"], + address.live_cells_count end end @@ -960,9 +1034,13 @@ class NodeDataProcessorTest < ActiveSupport::TestCase Address.find_or_create_address(lock2, node_block.header.timestamp) 300.times do |i| if i % 2 == 0 - node_block.transactions.first.outputs << CKB::Types::Output.new(capacity: 30000 * 10**8, lock: lock1) + node_block.transactions.first.outputs << CKB::Types::Output.new( + capacity: 30000 * 10**8, lock: lock1, + ) else - node_block.transactions.first.outputs << CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock2) + node_block.transactions.first.outputs << CKB::Types::Output.new( + capacity: 40000 * 10**8, lock: lock2, + ) end node_block.transactions.first.outputs_data << "0x" end @@ -972,15 +1050,18 @@ class NodeDataProcessorTest < ActiveSupport::TestCase new_local_block.contained_addresses.sum(:balance) address = new_local_block.contained_addresses.first - snapshot = AddressBlockSnapshot.find_by(block_id: new_local_block.id, address_id: address.id) + snapshot = AddressBlockSnapshot.find_by(block_id: new_local_block.id, + address_id: address.id) assert_equal snapshot.final_state["balance"], address.balance end end test "#process_block should update block's contained address's dao_ckb_transactions_count" do - block1 = create(:block, :with_block_hash, number: DEFAULT_NODE_BLOCK_NUMBER - 2) + block1 = create(:block, :with_block_hash, + number: DEFAULT_NODE_BLOCK_NUMBER - 2) tx1 = create(:ckb_transaction, block: block1) - block2 = create(:block, :with_block_hash, number: DEFAULT_NODE_BLOCK_NUMBER - 1) + block2 = create(:block, :with_block_hash, + number: DEFAULT_NODE_BLOCK_NUMBER - 1) tx2 = create(:ckb_transaction, block: block2) tx3 = create(:ckb_transaction, block: block2) tx4 = create(:ckb_transaction, block: block2) @@ -1003,13 +1084,23 @@ class NodeDataProcessorTest < ActiveSupport::TestCase header = CKB::Types::BlockHeader.new(compact_target: "0x1000", hash: "0x#{SecureRandom.hex(32)}", number: DEFAULT_NODE_BLOCK_NUMBER, parent_hash: "0x#{SecureRandom.hex(32)}", nonce: 1757392074788233522, timestamp: CkbUtils.time_in_milliseconds(Time.current), transactions_root: "0x#{SecureRandom.hex(32)}", proposals_hash: "0x#{SecureRandom.hex(32)}", extra_hash: "0x#{SecureRandom.hex(32)}", version: 0, epoch: 1, dao: "0x01000000000000000000c16ff286230000a3a65e97fd03000057c138586f0000") inputs = [ - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx1.tx_hash, index: 0)), - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx2.tx_hash, index: 1)), - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx3.tx_hash, index: 2)) + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx1.tx_hash, index: 0, + )), + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx2.tx_hash, index: 1, + )), + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx3.tx_hash, index: 2, + )), ] inputs1 = [ - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx4.tx_hash, index: 0)), - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx5.tx_hash, index: 0)) + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx4.tx_hash, index: 0, + )), + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx5.tx_hash, index: 0, + )), ] lock1 = CKB::Types::Script.new(code_hash: Settings.secp_cell_type_hash, hash_type: "type", args: "0x#{SecureRandom.hex(20)}") @@ -1017,38 +1108,44 @@ class NodeDataProcessorTest < ActiveSupport::TestCase args: "0x#{SecureRandom.hex(20)}") lock3 = CKB::Types::Script.new(code_hash: Settings.secp_cell_type_hash, hash_type: "type", args: "0x#{SecureRandom.hex(20)}") - dao_type = CKB::Types::Script.new(code_hash: Settings.dao_type_hash, hash_type: "type", args: "0x") + dao_type = CKB::Types::Script.new(code_hash: Settings.dao_type_hash, + hash_type: "type", args: "0x") outputs = [ - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock1, type: dao_type), - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock2, type: dao_type), - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock3) + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock1, + type: dao_type), + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock2, + type: dao_type), + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock3), ] outputs1 = [ - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock1, type: dao_type), - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock2, type: dao_type), - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock3) + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock1, + type: dao_type), + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock2, + type: dao_type), + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock3), ] miner_lock = CKB::Types::Script.new(code_hash: Settings.secp_cell_type_hash, hash_type: "type", args: "0x#{SecureRandom.hex(20)}") cellbase_inputs = [ CKB::Types::Input.new( previous_output: CKB::Types::OutPoint.new( - tx_hash: "0x0000000000000000000000000000000000000000000000000000000000000000", index: 4294967295 + tx_hash: "0x0000000000000000000000000000000000000000000000000000000000000000", index: 4294967295, ), since: 3000 - ) + ), ] cellbase_outputs = [ - CKB::Types::Output.new(capacity: 200986682127, lock: miner_lock) + CKB::Types::Output.new(capacity: 200986682127, lock: miner_lock), ] transactions = [ CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs: cellbase_inputs, outputs: cellbase_outputs, outputs_data: %w[0x], witnesses: ["0x590000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd800000000"]), - CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs: inputs, - outputs: outputs, outputs_data: %w[0x0000000000000000 0x0000000000000000 0x], witnesses: ["0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000"]), + CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs:, + outputs:, outputs_data: %w[0x0000000000000000 0x0000000000000000 0x], witnesses: ["0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000"]), CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs: inputs1, - outputs: outputs1, outputs_data: %w[0x0000000000000000 0x0000000000000000 0x], witnesses: ["0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000"]) + outputs: outputs1, outputs_data: %w[0x0000000000000000 0x0000000000000000 0x], witnesses: ["0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000"]), ] - node_block = CKB::Types::Block.new(uncles: [], proposals: [], transactions: transactions, header: header) + node_block = CKB::Types::Block.new(uncles: [], proposals: [], + transactions:, header:) node_data_processor.process_block(node_block) address1 = Address.find_by(lock_hash: lock1.compute_hash) address2 = Address.find_by(lock_hash: lock2.compute_hash) @@ -1060,9 +1157,11 @@ class NodeDataProcessorTest < ActiveSupport::TestCase end test "should recalculate block's contained address's dao_ckb_transactions_count when block is invalid" do - block1 = create(:block, :with_block_hash, number: DEFAULT_NODE_BLOCK_NUMBER - 2) + block1 = create(:block, :with_block_hash, + number: DEFAULT_NODE_BLOCK_NUMBER - 2) tx1 = create(:ckb_transaction, block: block1) - block2 = create(:block, :with_block_hash, number: DEFAULT_NODE_BLOCK_NUMBER - 1) + block2 = create(:block, :with_block_hash, + number: DEFAULT_NODE_BLOCK_NUMBER - 1) tx2 = create(:ckb_transaction, block: block2) tx3 = create(:ckb_transaction, block: block2) tx4 = create(:ckb_transaction, block: block2) @@ -1086,13 +1185,23 @@ class NodeDataProcessorTest < ActiveSupport::TestCase header = CKB::Types::BlockHeader.new(compact_target: "0x1000", hash: "0x#{SecureRandom.hex(32)}", number: DEFAULT_NODE_BLOCK_NUMBER, parent_hash: "0x#{SecureRandom.hex(32)}", nonce: 1757392074788233522, timestamp: CkbUtils.time_in_milliseconds(Time.current), transactions_root: "0x#{SecureRandom.hex(32)}", proposals_hash: "0x#{SecureRandom.hex(32)}", extra_hash: "0x#{SecureRandom.hex(32)}", version: 0, epoch: 1, dao: "0x01000000000000000000c16ff286230000a3a65e97fd03000057c138586f0000") inputs = [ - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx1.tx_hash, index: 0)), - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx2.tx_hash, index: 1)), - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx3.tx_hash, index: 2)) + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx1.tx_hash, index: 0, + )), + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx2.tx_hash, index: 1, + )), + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx3.tx_hash, index: 2, + )), ] inputs1 = [ - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx4.tx_hash, index: 0)), - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx5.tx_hash, index: 0)) + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx4.tx_hash, index: 0, + )), + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx5.tx_hash, index: 0, + )), ] lock1 = CKB::Types::Script.new(code_hash: Settings.secp_cell_type_hash, hash_type: "type", args: "0x#{SecureRandom.hex(20)}") @@ -1100,44 +1209,51 @@ class NodeDataProcessorTest < ActiveSupport::TestCase args: "0x#{SecureRandom.hex(20)}") lock3 = CKB::Types::Script.new(code_hash: Settings.secp_cell_type_hash, hash_type: "type", args: "0x#{SecureRandom.hex(20)}") - dao_type = CKB::Types::Script.new(code_hash: Settings.dao_type_hash, hash_type: "type", args: "0x") + dao_type = CKB::Types::Script.new(code_hash: Settings.dao_type_hash, + hash_type: "type", args: "0x") outputs = [ - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock1, type: dao_type), - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock2, type: dao_type), - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock3) + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock1, + type: dao_type), + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock2, + type: dao_type), + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock3), ] outputs1 = [ - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock1, type: dao_type), - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock2, type: dao_type), - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock3) + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock1, + type: dao_type), + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock2, + type: dao_type), + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock3), ] miner_lock = CKB::Types::Script.new(code_hash: Settings.secp_cell_type_hash, hash_type: "type", args: "0x#{SecureRandom.hex(20)}") cellbase_inputs = [ CKB::Types::Input.new( previous_output: CKB::Types::OutPoint.new( - tx_hash: "0x0000000000000000000000000000000000000000000000000000000000000000", index: 4294967295 + tx_hash: "0x0000000000000000000000000000000000000000000000000000000000000000", index: 4294967295, ), since: 3000 - ) + ), ] cellbase_outputs = [ - CKB::Types::Output.new(capacity: 200986682127, lock: miner_lock) + CKB::Types::Output.new(capacity: 200986682127, lock: miner_lock), ] transactions = [ CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs: cellbase_inputs, outputs: cellbase_outputs, outputs_data: %w[0x], witnesses: ["0x590000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd800000000"]), - CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs: inputs, - outputs: outputs, outputs_data: %w[0x0000000000000000 0x0000000000000000 0x], witnesses: ["0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000"]), + CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs:, + outputs:, outputs_data: %w[0x0000000000000000 0x0000000000000000 0x], witnesses: ["0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000"]), CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs: inputs1, - outputs: outputs1, outputs_data: %w[0x0000000000000000 0x0000000000000000 0x], witnesses: ["0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000"]) + outputs: outputs1, outputs_data: %w[0x0000000000000000 0x0000000000000000 0x], witnesses: ["0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000"]), ] - node_block = CKB::Types::Block.new(uncles: [], proposals: [], transactions: transactions, header: header) + node_block = CKB::Types::Block.new(uncles: [], proposals: [], + transactions:, header:) block = node_data_processor.process_block(node_block) address1 = Address.find_by(lock_hash: lock1.compute_hash) address2 = Address.find_by(lock_hash: lock2.compute_hash) address3 = Address.find_by(lock_hash: lock3.compute_hash) CkbSync::Api.any_instance.stubs(:get_tip_block_number).returns(block.number + 1) - VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", record: :new_episodes) do + VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", + record: :new_episodes) do node_data_processor.call end @@ -1154,7 +1270,8 @@ class NodeDataProcessorTest < ActiveSupport::TestCase VCR.use_cassette("blocks/12", record: :new_episodes) do new_local_block = node_data_processor.call - assert_equal origin_live_cells_count - 1, new_local_block.contained_addresses.sum(:live_cells_count) + assert_equal origin_live_cells_count - 1, + new_local_block.contained_addresses.sum(:live_cells_count) end end @@ -1163,12 +1280,14 @@ class NodeDataProcessorTest < ActiveSupport::TestCase local_block = Block.find_by(number: 12) address = local_block.contained_addresses.first origin_balance_occupied = 300 * 10**8 - address.update(balance_occupied: origin_balance_occupied, mined_blocks_count: 1) + address.update(balance_occupied: origin_balance_occupied, + mined_blocks_count: 1) local_block.update(block_hash: "0x419c632366c8eb9635acbb39ea085f7552ae62e1fdd480893375334a0f37d1bx") VCR.use_cassette("blocks/12", record: :new_episodes) do new_local_block = node_data_processor.call - assert_equal 0, new_local_block.contained_addresses.sum(:balance_occupied) + assert_equal 0, + new_local_block.contained_addresses.sum(:balance_occupied) end end @@ -1178,7 +1297,8 @@ class NodeDataProcessorTest < ActiveSupport::TestCase local_block = node_data_processor.call target_block = local_block.target_block block_economic_state = CkbSync::Api.instance.get_block_economic_state(local_block.target_block.block_hash) - expected_reward = CkbUtils.block_reward(local_block.number, block_economic_state) + expected_reward = CkbUtils.block_reward(local_block.number, + block_economic_state) assert_equal expected_reward, target_block.reward end @@ -1191,7 +1311,9 @@ class NodeDataProcessorTest < ActiveSupport::TestCase target_block = local_block.target_block block_header = Struct.new(:hash, :number) block_economic_state = CkbSync::Api.instance.get_block_economic_state(local_block.target_block.block_hash) - expected_primary_reward = CkbUtils.primary_reward(local_block.target_block_number, block_economic_state) + expected_primary_reward = CkbUtils.primary_reward( + local_block.target_block_number, block_economic_state + ) assert_equal expected_primary_reward, target_block.primary_reward end @@ -1204,7 +1326,9 @@ class NodeDataProcessorTest < ActiveSupport::TestCase target_block = local_block.target_block block_header = Struct.new(:hash, :number) block_economic_state = CkbSync::Api.instance.get_block_economic_state(local_block.target_block.block_hash) - expected_secondary_reward = CkbUtils.secondary_reward(local_block.target_block_number, block_economic_state) + expected_secondary_reward = CkbUtils.secondary_reward( + local_block.target_block_number, block_economic_state + ) assert_equal expected_secondary_reward, target_block.secondary_reward end @@ -1213,8 +1337,11 @@ class NodeDataProcessorTest < ActiveSupport::TestCase test "should do nothing on the local tip block's target block reward status when there is no target block" do prepare_node_data(9) local_block = Block.find_by(number: 9) - VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", record: :new_episodes) do - assert_no_changes -> { local_block.reload.target_block_reward_status } do + VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", + record: :new_episodes) do + assert_no_changes -> { + local_block.reload.target_block_reward_status + } do node_data_processor.call end end @@ -1224,7 +1351,9 @@ class NodeDataProcessorTest < ActiveSupport::TestCase prepare_node_data(12) target_block = Block.find_by(number: 2) VCR.use_cassette("blocks/12", record: :new_episodes) do - assert_changes -> { target_block.reload.received_tx_fee }, from: 0, to: 20 do + assert_changes -> { + target_block.reload.received_tx_fee + }, from: 0, to: 20 do node_data_processor.call end end @@ -1232,7 +1361,8 @@ class NodeDataProcessorTest < ActiveSupport::TestCase test "should do nothing on the local tip block target block's received tx fee when there is no target block" do prepare_node_data(9) - VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", record: :new_episodes) do + VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", + record: :new_episodes) do assert_nothing_raised do node_data_processor.call end @@ -1243,7 +1373,9 @@ class NodeDataProcessorTest < ActiveSupport::TestCase prepare_node_data(12) target_block = Block.find_by(number: 2) VCR.use_cassette("blocks/12", record: :new_episodes) do - assert_changes -> { target_block.reload.reward_status }, from: "pending", to: "issued" do + assert_changes -> { + target_block.reload.reward_status + }, from: "pending", to: "issued" do node_data_processor.call end end @@ -1251,7 +1383,8 @@ class NodeDataProcessorTest < ActiveSupport::TestCase test "should do nothing on the local tip block target block's reward status when there is no target block" do prepare_node_data(9) - VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", record: :new_episodes) do + VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", + record: :new_episodes) do assert_nothing_raised do node_data_processor.call end @@ -1262,7 +1395,9 @@ class NodeDataProcessorTest < ActiveSupport::TestCase prepare_node_data(12) target_block = Block.find_by(number: 2) VCR.use_cassette("blocks/12", record: :new_episodes) do - assert_changes -> { target_block.reload.received_tx_fee_status }, from: "pending", to: "calculated" do + assert_changes -> { + target_block.reload.received_tx_fee_status + }, from: "pending", to: "calculated" do node_data_processor.call end end @@ -1270,7 +1405,8 @@ class NodeDataProcessorTest < ActiveSupport::TestCase test "should do nothing on the local tip block target block's received_tx_fee_status when there is no target block" do prepare_node_data(9) - VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", record: :new_episodes) do + VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", + record: :new_episodes) do assert_nothing_raised do node_data_processor.call end @@ -1285,24 +1421,24 @@ class NodeDataProcessorTest < ActiveSupport::TestCase primary: "0x174876e800", secondary: "0x0", tx_fee: "0x0", - proposal_reward: "0x0" - ) + proposal_reward: "0x0", + ), ) CkbSync::Api.any_instance.stubs(:get_block_economic_state).returns( OpenStruct.new(miner_reward: CKB::Types::MinerReward.new( primary: "0x174876e800", secondary: "0xa", committed: "0xa", - proposal: "0xa" - )) + proposal: "0xa", + )), ) CkbSync::Api.any_instance.stubs(:get_epoch_by_number).returns( CKB::Types::Epoch.new( compact_target: "0x1000", length: "0x07d0", number: "0x0", - start_number: "0x0" - ) + start_number: "0x0", + ), ) VCR.use_cassette("blocks/12") do node_block = CkbSync::Api.instance.get_block_by_number(12) @@ -1313,10 +1449,11 @@ class NodeDataProcessorTest < ActiveSupport::TestCase cellbase = Cellbase.new(block) expected_cellbase_display_inputs = [ CkbUtils.hash_value_to_s(id: nil, from_cellbase: true, capacity: nil, occupied_capacity: nil, - address_hash: nil, target_block_number: cellbase.target_block_number, generated_tx_hash: block.cellbase.tx_hash) + address_hash: nil, target_block_number: cellbase.target_block_number, generated_tx_hash: block.cellbase.tx_hash), ] - assert_equal expected_cellbase_display_inputs, block.cellbase.display_inputs + assert_equal expected_cellbase_display_inputs, + block.cellbase.display_inputs end end end @@ -1330,16 +1467,16 @@ class NodeDataProcessorTest < ActiveSupport::TestCase primary: "0x174876e800", secondary: "0x0", tx_fee: "0x0", - proposal_reward: "0x0" - ) + proposal_reward: "0x0", + ), ) CkbSync::Api.any_instance.stubs(:get_block_economic_state).returns( OpenStruct.new(miner_reward: CKB::Types::MinerReward.new( primary: "0x174876e800", secondary: "0xa", committed: "0xa", - proposal: "0xa" - )) + proposal: "0xa", + )), ) node_block = CkbSync::Api.instance.get_block_by_number(DEFAULT_NODE_BLOCK_NUMBER) create(:block, :with_block_hash, number: node_block.header.number - 1) @@ -1351,7 +1488,7 @@ class NodeDataProcessorTest < ActiveSupport::TestCase cellbase = Cellbase.new(local_block) expected_display_outputs = [ CkbUtils.hash_value_to_s(id: output.id, capacity: output.capacity, occupied_capacity: output.occupied_capacity, - address_hash: output.address_hash, target_block_number: cellbase.target_block_number, base_reward: cellbase.base_reward, commit_reward: cellbase.commit_reward, proposal_reward: cellbase.proposal_reward, secondary_reward: cellbase.secondary_reward, status: "live", consumed_tx_hash: nil) + address_hash: output.address_hash, target_block_number: cellbase.target_block_number, base_reward: cellbase.base_reward, commit_reward: cellbase.commit_reward, proposal_reward: cellbase.proposal_reward, secondary_reward: cellbase.secondary_reward, status: "live", consumed_tx_hash: nil), ] assert_equal expected_display_outputs, local_block_cell_outputs @@ -1365,24 +1502,24 @@ class NodeDataProcessorTest < ActiveSupport::TestCase primary: "0x174876e800", secondary: "0x0", tx_fee: "0x0", - proposal_reward: "0x0" - ) + proposal_reward: "0x0", + ), ) CkbSync::Api.any_instance.stubs(:get_block_economic_state).returns( OpenStruct.new(miner_reward: CKB::Types::MinerReward.new( primary: "0x174876e800", secondary: "0xa", committed: "0xa", - proposal: "0xa" - )) + proposal: "0xa", + )), ) CkbSync::Api.any_instance.stubs(:get_epoch_by_number).returns( CKB::Types::Epoch.new( compact_target: "0x1000", length: "0x07d0", number: "0x0", - start_number: "0x0" - ) + start_number: "0x0", + ), ) VCR.use_cassette("genesis_block") do node_block = CkbSync::Api.instance.get_block_by_number(0) @@ -1394,9 +1531,10 @@ class NodeDataProcessorTest < ActiveSupport::TestCase block.cellbase.cell_outputs.order(:id).map do |cell_output| consumed_tx_hash = cell_output.live? ? nil : cell_output.consumed_by.tx_hash CkbUtils.hash_value_to_s(id: cell_output.id, capacity: cell_output.capacity, occupied_capacity: cell_output.occupied_capacity, - address_hash: cell_output.address_hash, target_block_number: cellbase.target_block_number, base_reward: cellbase.base_reward, commit_reward: cellbase.commit_reward, proposal_reward: cellbase.proposal_reward, secondary_reward: cellbase.secondary_reward, status: cell_output.status, consumed_tx_hash: consumed_tx_hash) + address_hash: cell_output.address_hash, target_block_number: cellbase.target_block_number, base_reward: cellbase.base_reward, commit_reward: cellbase.commit_reward, proposal_reward: cellbase.proposal_reward, secondary_reward: cellbase.secondary_reward, status: cell_output.status, consumed_tx_hash:) end - assert_equal expected_cellbase_display_outputs, block.cellbase.display_outputs + assert_equal expected_cellbase_display_outputs, + block.cellbase.display_outputs end end @@ -1407,8 +1545,8 @@ class NodeDataProcessorTest < ActiveSupport::TestCase compact_target: "0x1000", length: "0x07d0", number: "0x0", - start_number: "0x0" - ) + start_number: "0x0", + ), ) CkbSync::Api.any_instance.stubs(:get_cellbase_output_capacity_details).returns( CKB::Types::BlockReward.new( @@ -1416,16 +1554,16 @@ class NodeDataProcessorTest < ActiveSupport::TestCase primary: "0x174876e800", secondary: "0x0", tx_fee: "0x0", - proposal_reward: "0x0" - ) + proposal_reward: "0x0", + ), ) CkbSync::Api.any_instance.stubs(:get_block_economic_state).returns( OpenStruct.new(miner_reward: CKB::Types::MinerReward.new( primary: "0x174876e800", secondary: "0xa", committed: "0xa", - proposal: "0xa" - )) + proposal: "0xa", + )), ) VCR.use_cassette("blocks/12") do assert_difference "Block.count", 1 do @@ -1437,10 +1575,11 @@ class NodeDataProcessorTest < ActiveSupport::TestCase cell_output = block.cellbase.cell_outputs.first expected_cellbase_display_outputs = [ CkbUtils.hash_value_to_s(id: cell_output.id, - capacity: cell_output.capacity, occupied_capacity: cell_output.occupied_capacity, address_hash: cell_output.address_hash, target_block_number: cellbase.target_block_number, base_reward: cellbase.base_reward, commit_reward: cellbase.commit_reward, proposal_reward: cellbase.proposal_reward, secondary_reward: cellbase.secondary_reward, status: "live", consumed_tx_hash: nil) + capacity: cell_output.capacity, occupied_capacity: cell_output.occupied_capacity, address_hash: cell_output.address_hash, target_block_number: cellbase.target_block_number, base_reward: cellbase.base_reward, commit_reward: cellbase.commit_reward, proposal_reward: cellbase.proposal_reward, secondary_reward: cellbase.secondary_reward, status: "live", consumed_tx_hash: nil), ] - assert_equal expected_cellbase_display_outputs, block.cellbase.display_outputs + assert_equal expected_cellbase_display_outputs, + block.cellbase.display_outputs end end end @@ -1452,8 +1591,11 @@ class NodeDataProcessorTest < ActiveSupport::TestCase assert_not_empty local_block.uncle_blocks - VCR.use_cassette("blocks/#{HAS_UNCLES_BLOCK_NUMBER}", record: :new_episodes) do - assert_changes -> { local_block.uncle_blocks.count }, from: local_block.uncle_blocks.count, to: 0 do + VCR.use_cassette("blocks/#{HAS_UNCLES_BLOCK_NUMBER}", + record: :new_episodes) do + assert_changes -> { + local_block.uncle_blocks.count + }, from: local_block.uncle_blocks.count, to: 0 do node_data_processor.call end end @@ -1466,8 +1608,11 @@ class NodeDataProcessorTest < ActiveSupport::TestCase assert_not_empty local_block.ckb_transactions - VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", record: :new_episodes) do - assert_changes -> { local_block.ckb_transactions.count }, from: local_block.ckb_transactions.count, to: 0 do + VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", + record: :new_episodes) do + assert_changes -> { + local_block.ckb_transactions.count + }, from: local_block.ckb_transactions.count, to: 0 do node_data_processor.call end end @@ -1480,8 +1625,11 @@ class NodeDataProcessorTest < ActiveSupport::TestCase assert_not_empty local_block.cell_inputs - VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", record: :new_episodes) do - assert_changes -> { local_block.cell_inputs.count }, from: local_block.cell_inputs.count, to: 0 do + VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", + record: :new_episodes) do + assert_changes -> { + local_block.cell_inputs.count + }, from: local_block.cell_inputs.count, to: 0 do node_data_processor.call end end @@ -1494,7 +1642,8 @@ class NodeDataProcessorTest < ActiveSupport::TestCase assert_not_empty local_block.cell_outputs - VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", record: :new_episodes) do + VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", + record: :new_episodes) do assert_changes -> { CellOutput.where(block: local_block).count }, from: CellOutput.where(block: local_block).count, to: 0 do @@ -1511,7 +1660,8 @@ class NodeDataProcessorTest < ActiveSupport::TestCase assert_not_empty origin_lock_scripts - VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", record: :new_episodes) do + VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", + record: :new_episodes) do assert_changes -> { CellOutput.where(block: local_block).map(&:lock_script).count }, from: origin_lock_scripts.count, to: 0 do @@ -1528,7 +1678,8 @@ class NodeDataProcessorTest < ActiveSupport::TestCase assert_not_empty origin_type_scripts - VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", record: :new_episodes) do + VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", + record: :new_episodes) do assert_changes -> { CellOutput.where(block: local_block).map(&:type_script).count }, from: origin_type_scripts.count, to: 0 do @@ -1542,7 +1693,8 @@ class NodeDataProcessorTest < ActiveSupport::TestCase local_block = Block.find_by(number: 30) local_block.update(number: 100_000_000) - VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", record: :new_episodes) do + VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", + record: :new_episodes) do assert_nil node_data_processor.call end end @@ -1564,8 +1716,11 @@ class NodeDataProcessorTest < ActiveSupport::TestCase # ApplicationRecord.connection.execute "CALL sync_full_account_book()" local_block.update(block_hash: "0x419c632366c8eb9635acbb39ea085f7552ae62e1fdd480893375334a0f37d1bx") - VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", record: :new_episodes) do - assert_difference -> { local_block.contained_addresses.map(&:ckb_transactions_count).flatten.sum }, -1 do + VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", + record: :new_episodes) do + assert_difference -> { + local_block.contained_addresses.map(&:ckb_transactions_count).flatten.sum + }, -1 do node_data_processor.call end end @@ -1578,8 +1733,11 @@ class NodeDataProcessorTest < ActiveSupport::TestCase ckb_transaction_ids = local_block.ckb_transactions.pluck(:id) balance_diff = CellOutput.where(ckb_transaction_id: ckb_transaction_ids).sum(:capacity) - VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", record: :new_episodes) do - assert_difference -> { local_block.contained_addresses.sum(:balance) }, -balance_diff do + VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", + record: :new_episodes) do + assert_difference -> { + local_block.contained_addresses.sum(:balance) + }, -balance_diff do node_data_processor.call end end @@ -1591,7 +1749,9 @@ class NodeDataProcessorTest < ActiveSupport::TestCase local_block.update(block_hash: "0x419c632366c8eb9635acbb39ea085f7552ae62e1fdd480893375334a0f37d1bx") target_block = local_block.target_block VCR.use_cassette("blocks/12", record: :new_episodes) do - assert_changes -> { target_block.reload.received_tx_fee }, from: target_block.received_tx_fee, to: 0 do + assert_changes -> { + target_block.reload.received_tx_fee + }, from: target_block.received_tx_fee, to: 0 do node_data_processor.call end end @@ -1601,7 +1761,8 @@ class NodeDataProcessorTest < ActiveSupport::TestCase prepare_node_data(19) local_block = Block.find_by(number: 19) local_block.update(block_hash: "0x419c632366c8eb9635acbb39ea085f7552ae62e1fdd480893375334a0f37d1bx") - VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", record: :new_episodes) do + VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", + record: :new_episodes) do assert_nothing_raised do node_data_processor.call end @@ -1614,7 +1775,9 @@ class NodeDataProcessorTest < ActiveSupport::TestCase local_block.update(block_hash: "0x419c632366c8eb9635acbb39ea085f7552ae62e1fdd480893375334a0f37d1bx") target_block = local_block.target_block VCR.use_cassette("blocks/12") do - assert_changes -> { target_block.reload.reward_status }, from: "issued", to: "pending" do + assert_changes -> { + target_block.reload.reward_status + }, from: "issued", to: "pending" do node_data_processor.call end end @@ -1624,7 +1787,8 @@ class NodeDataProcessorTest < ActiveSupport::TestCase prepare_node_data(19) local_block = Block.find_by(number: 19) local_block.update(block_hash: "0x419c632366c8eb9635acbb39ea085f7552ae62e1fdd480893375334a0f37d1bx") - VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", record: :new_episodes) do + VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", + record: :new_episodes) do assert_nothing_raised do node_data_processor.call end @@ -1637,7 +1801,9 @@ class NodeDataProcessorTest < ActiveSupport::TestCase local_block.update(block_hash: "0x419c632366c8eb9635acbb39ea085f7552ae62e1fdd480893375334a0f37d1bx") target_block = local_block.target_block VCR.use_cassette("blocks/12", record: :new_episodes) do - assert_changes -> { target_block.reload.received_tx_fee_status }, from: "calculated", to: "pending" do + assert_changes -> { + target_block.reload.received_tx_fee_status + }, from: "calculated", to: "pending" do node_data_processor.call end end @@ -1647,7 +1813,8 @@ class NodeDataProcessorTest < ActiveSupport::TestCase prepare_node_data(19) local_block = Block.find_by(number: 19) local_block.update(block_hash: "0x419c632366c8eb9635acbb39ea085f7552ae62e1fdd480893375334a0f37d1bx") - VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", record: :new_episodes) do + VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", + record: :new_episodes) do assert_nothing_raised do node_data_processor.call end @@ -1682,7 +1849,8 @@ class NodeDataProcessorTest < ActiveSupport::TestCase node_block = CkbSync::Api.instance.get_block_by_number(DEFAULT_NODE_BLOCK_NUMBER) create(:block, :with_block_hash, number: node_block.header.number - 1) node_output = node_block.transactions.first.outputs.first - node_block.transactions.first.outputs_data[0] = "0x421d0000000000000000000000000000" + node_block.transactions.first.outputs_data[0] = + "0x421d0000000000000000000000000000" node_output.type = CKB::Types::Script.new(code_hash: Settings.sudt_cell_type_hash, args: issuer_address.lock_hash, hash_type: "type") create(:udt, code_hash: Settings.sudt_cell_type_hash, type_hash: node_output.type.compute_hash, @@ -1700,7 +1868,8 @@ class NodeDataProcessorTest < ActiveSupport::TestCase node_block = CkbSync::Api.instance.get_block_by_number(DEFAULT_NODE_BLOCK_NUMBER) create(:block, :with_block_hash, number: node_block.header.number - 1) node_output = node_block.transactions.first.outputs.first - node_block.transactions.first.outputs_data[0] = "0x421d0000000000000000000000000000" + node_block.transactions.first.outputs_data[0] = + "0x421d0000000000000000000000000000" node_output.type = CKB::Types::Script.new(code_hash: Settings.sudt1_cell_type_hash, args: issuer_address.lock_hash, hash_type: "type") create(:udt, code_hash: Settings.sudt_cell_type_hash, type_hash: node_output.type.compute_hash, @@ -1718,7 +1887,8 @@ class NodeDataProcessorTest < ActiveSupport::TestCase node_block = CkbSync::Api.instance.get_block_by_number(DEFAULT_NODE_BLOCK_NUMBER) create(:block, :with_block_hash, number: node_block.header.number - 1) node_output = node_block.transactions.first.outputs.first - node_block.transactions.first.outputs_data[0] = "0x421d0000000000000000000000000000" + node_block.transactions.first.outputs_data[0] = + "0x421d0000000000000000000000000000" node_output.type = CKB::Types::Script.new(code_hash: Settings.sudt_cell_type_hash, args: issuer_address.lock_hash, hash_type: "type") create(:udt, code_hash: Settings.sudt_cell_type_hash, type_hash: node_output.type.compute_hash, @@ -1739,7 +1909,8 @@ class NodeDataProcessorTest < ActiveSupport::TestCase node_block = CkbSync::Api.instance.get_block_by_number(DEFAULT_NODE_BLOCK_NUMBER) create(:block, :with_block_hash, number: node_block.header.number - 1) node_output = node_block.transactions.first.outputs.first - node_block.transactions.first.outputs_data[0] = "0x421d0000000000000000000000000000" + node_block.transactions.first.outputs_data[0] = + "0x421d0000000000000000000000000000" node_output.type = CKB::Types::Script.new(code_hash: CkbSync::Api.instance.token_script_code_hash, args: "0x3ae8bce37310b44b4dec3ce6b03308ba39b603de000000020000000c", hash_type: "type") create(:udt, code_hash: CkbSync::Api.instance.token_script_code_hash, type_hash: node_output.type.compute_hash, @@ -1762,11 +1933,11 @@ class NodeDataProcessorTest < ActiveSupport::TestCase VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}") do node_block = CkbSync::Api.instance.get_block_by_number(DEFAULT_NODE_BLOCK_NUMBER) create(:block, :with_block_hash, number: node_block.header.number - 1) - previous_ckb_transaction = create(:ckb_transaction, block: block) + previous_ckb_transaction = create(:ckb_transaction, block:) token_type_script = CKB::Types::Script.new(code_hash: CkbSync::Api.instance.token_script_code_hash, args: "0x3ae8bce37310b44b4dec3ce6b03308ba39b603de000000020000000c", hash_type: "type") previous_cell_output = create(:cell_output, capacity: 1000 * 10**8, tx_hash: previous_ckb_transaction.tx_hash, - ckb_transaction: previous_ckb_transaction, block: block, cell_type: "m_nft_token", address: address, udt_amount: "12", cell_index: 0, data: "0x421d0000000000000000000000000000", type_hash: token_type_script.compute_hash) + ckb_transaction: previous_ckb_transaction, block:, cell_type: "m_nft_token", address:, udt_amount: "12", cell_index: 0, data: "0x421d0000000000000000000000000000", type_hash: token_type_script.compute_hash) previous_cell_output_lock_script = create(:lock_script, code_hash: Settings.secp_cell_type_hash, args: "0xb2e61ff569acf041b3c2c17724e2379c581eeac3", hash_type: "type") previous_cell_output_type_script = create(:type_script, @@ -1774,8 +1945,9 @@ class NodeDataProcessorTest < ActiveSupport::TestCase previous_cell_output.type_script_id = previous_cell_output_type_script.id previous_cell_output.lock_script_id = previous_cell_output_lock_script.id type_hash = CKB::Types::Script.new(**previous_cell_output_type_script.to_node).compute_hash - udt = create(:udt, type_hash: type_hash, udt_type: "m_nft_token") - address.udt_accounts.create(udt_type: "m_nft_token", type_hash: type_hash, udt: udt) + udt = create(:udt, type_hash:, udt_type: "m_nft_token") + address.udt_accounts.create(udt_type: "m_nft_token", + type_hash:, udt:) input = CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: previous_cell_output.tx_hash, index: 0)) output = CKB::Types::Output.new(capacity: 150 * 10**8, @@ -1797,7 +1969,8 @@ class NodeDataProcessorTest < ActiveSupport::TestCase node_block = CkbSync::Api.instance.get_block_by_number(DEFAULT_NODE_BLOCK_NUMBER) create(:block, :with_block_hash, number: node_block.header.number - 1) node_output = node_block.transactions.first.outputs.first - node_block.transactions.first.outputs_data[0] = "0x421d0000000000000000000000000000" + node_block.transactions.first.outputs_data[0] = + "0x421d0000000000000000000000000000" type = create(:type_script, code_hash: CkbSync::Api.instance.token_class_script_code_hash, hash_type: "type", args: "0x3ae8bce37310b44b4dec3ce6b03308ba39b603de00000002") create(:cell_output, :with_full_transaction_but_no_type_script, type_script_id: type.id, @@ -1821,10 +1994,11 @@ class NodeDataProcessorTest < ActiveSupport::TestCase node_output = node_block.transactions.first.outputs.first node_output.type = CKB::Types::Script.new(code_hash: Settings.sudt_cell_type_hash, args: "0xb2e61ff569acf041b3c2c17724e2379c581eeac3") - create(:udt, code_hash: Settings.sudt_cell_type_hash, type_hash: node_output.type.compute_hash) + create(:udt, code_hash: Settings.sudt_cell_type_hash, + type_hash: node_output.type.compute_hash) address_hash = CkbUtils.generate_address(node_output.lock) address = Address.find_by_address_hash(address_hash) - create(:udt_account, code_hash: Settings.sudt_cell_type_hash, address: address, + create(:udt_account, code_hash: Settings.sudt_cell_type_hash, address:, type_hash: node_output.type.compute_hash) assert_difference -> { address.udt_accounts.count }, 0 do @@ -1841,11 +2015,13 @@ class NodeDataProcessorTest < ActiveSupport::TestCase node_output = node_block.transactions.first.outputs.first node_output.type = CKB::Types::Script.new(code_hash: Settings.sudt_cell_type_hash, args: "0xb2e61ff569acf041b3c2c17724e2379c581eeac3", hash_type: "type") - create(:udt, code_hash: Settings.sudt_cell_type_hash, type_hash: node_output.type.compute_hash) - node_block.transactions.first.outputs_data[0] = "0x000050ad321ea12e0000000000000000" + create(:udt, code_hash: Settings.sudt_cell_type_hash, + type_hash: node_output.type.compute_hash) + node_block.transactions.first.outputs_data[0] = + "0x000050ad321ea12e0000000000000000" address_hash = CkbUtils.generate_address(node_output.lock) address = Address.find_by_address_hash(address_hash) - create(:udt_account, code_hash: Settings.sudt_cell_type_hash, address: address, + create(:udt_account, code_hash: Settings.sudt_cell_type_hash, address:, type_hash: node_output.type.compute_hash) udt_account = address.udt_accounts.find_by(type_hash: node_output.type.compute_hash) @@ -1869,23 +2045,29 @@ class NodeDataProcessorTest < ActiveSupport::TestCase args: "0xb2e61ff569acf041b3c2c17724e2379c581eeac2", hash_type: "type") node_output.type = CKB::Types::Script.new(code_hash: Settings.sudt_cell_type_hash, args: "0xb2e61ff569acf041b3c2c17724e2379c581eeac3", hash_type: "type") - create(:udt, code_hash: Settings.sudt_cell_type_hash, type_hash: node_output.type.compute_hash) - create(:udt, code_hash: Settings.sudt_cell_type_hash, type_hash: new_node_output.type.compute_hash) - node_block.transactions.first.outputs_data[0] = "0x000050ad321ea12e0000000000000000" - node_block.transactions.first.outputs_data[1] = "0x0000909dceda82370000000000000000" + create(:udt, code_hash: Settings.sudt_cell_type_hash, + type_hash: node_output.type.compute_hash) + create(:udt, code_hash: Settings.sudt_cell_type_hash, + type_hash: new_node_output.type.compute_hash) + node_block.transactions.first.outputs_data[0] = + "0x000050ad321ea12e0000000000000000" + node_block.transactions.first.outputs_data[1] = + "0x0000909dceda82370000000000000000" address_hash = CkbUtils.generate_address(node_output.lock) address = Address.find_by_address_hash(address_hash) - create(:udt_account, code_hash: Settings.sudt_cell_type_hash, address: address, + create(:udt_account, code_hash: Settings.sudt_cell_type_hash, address:, type_hash: node_output.type.compute_hash) - create(:udt_account, code_hash: Settings.sudt_cell_type_hash, address: address, + create(:udt_account, code_hash: Settings.sudt_cell_type_hash, address:, type_hash: new_node_output.type.compute_hash) udt_account = address.udt_accounts.find_by(type_hash: node_output.type.compute_hash) udt_account1 = address.udt_accounts.find_by(type_hash: new_node_output.type.compute_hash) node_data_processor.process_block(node_block) - assert_equal CkbUtils.parse_udt_cell_data("0x000050ad321ea12e0000000000000000"), udt_account.reload.amount - assert_equal CkbUtils.parse_udt_cell_data("0x0000909dceda82370000000000000000"), udt_account1.reload.amount + assert_equal CkbUtils.parse_udt_cell_data("0x000050ad321ea12e0000000000000000"), + udt_account.reload.amount + assert_equal CkbUtils.parse_udt_cell_data("0x0000909dceda82370000000000000000"), + udt_account1.reload.amount end end @@ -1907,11 +2089,13 @@ class NodeDataProcessorTest < ActiveSupport::TestCase args: issuer_address1.lock_hash, hash_type: "type") udt = create(:udt, code_hash: Settings.sudt_cell_type_hash, type_hash: node_output.type.compute_hash, published: true, block_timestamp: node_block.header.timestamp) - node_block.transactions.first.outputs_data[0] = "0x000050ad321ea12e0000000000000000" - node_block.transactions.first.outputs_data[1] = "0x0000909dceda82370000000000000000" + node_block.transactions.first.outputs_data[0] = + "0x000050ad321ea12e0000000000000000" + node_block.transactions.first.outputs_data[1] = + "0x0000909dceda82370000000000000000" address_hash = CkbUtils.generate_address(node_output.lock) address = Address.find_by_address_hash(address_hash) - create(:udt_account, code_hash: Settings.sudt_cell_type_hash, address: address, + create(:udt_account, code_hash: Settings.sudt_cell_type_hash, address:, type_hash: node_output.type.compute_hash, published: true) node_data_processor.process_block(node_block) @@ -1935,22 +2119,28 @@ class NodeDataProcessorTest < ActiveSupport::TestCase args: "0xb2e61ff569acf041b3c2c17724e2379c581eeac2", hash_type: "type") node_output.type = CKB::Types::Script.new(code_hash: Settings.sudt_cell_type_hash, args: "0xb2e61ff569acf041b3c2c17724e2379c581eeac3", hash_type: "type") - udt1 = create(:udt, code_hash: Settings.sudt_cell_type_hash, type_hash: node_output.type.compute_hash) - udt2 = create(:udt, code_hash: Settings.sudt_cell_type_hash, type_hash: new_node_output.type.compute_hash) - node_block.transactions.first.outputs_data[0] = "0x000050ad321ea12e0000000000000000" - node_block.transactions.first.outputs_data[1] = "0x0000909dceda82370000000000000000" + udt1 = create(:udt, code_hash: Settings.sudt_cell_type_hash, + type_hash: node_output.type.compute_hash) + udt2 = create(:udt, code_hash: Settings.sudt_cell_type_hash, + type_hash: new_node_output.type.compute_hash) + node_block.transactions.first.outputs_data[0] = + "0x000050ad321ea12e0000000000000000" + node_block.transactions.first.outputs_data[1] = + "0x0000909dceda82370000000000000000" address_hash = CkbUtils.generate_address(node_output.lock) address = Address.find_by_address_hash(address_hash) - create(:udt_account, code_hash: Settings.sudt_cell_type_hash, address: address, + create(:udt_account, code_hash: Settings.sudt_cell_type_hash, address:, type_hash: node_output.type.compute_hash) - create(:udt_account, code_hash: Settings.sudt_cell_type_hash, address: address, + create(:udt_account, code_hash: Settings.sudt_cell_type_hash, address:, type_hash: new_node_output.type.compute_hash) node_data_processor.process_block(node_block) - assert_equal CkbUtils.parse_udt_cell_data("0x000050ad321ea12e0000000000000000"), udt1.reload.total_amount + assert_equal CkbUtils.parse_udt_cell_data("0x000050ad321ea12e0000000000000000"), + udt1.reload.total_amount assert_equal 1, udt1.addresses_count - assert_equal CkbUtils.parse_udt_cell_data("0x0000909dceda82370000000000000000"), udt2.reload.total_amount + assert_equal CkbUtils.parse_udt_cell_data("0x0000909dceda82370000000000000000"), + udt2.reload.total_amount assert_equal 1, udt2.addresses_count end end @@ -1961,12 +2151,14 @@ class NodeDataProcessorTest < ActiveSupport::TestCase CkbSync::Api.any_instance.stubs(:get_tip_block_number).returns(22) VCR.use_cassette("blocks/21") do node_block = CkbSync::Api.instance.get_block_by_number(21) - create(:block, :with_block_hash, number: node_block.header.number - 1, timestamp: 1557282351075) + create(:block, :with_block_hash, number: node_block.header.number - 1, + timestamp: 1557282351075) node_output = node_block.transactions.first.outputs.first node_output.type = CKB::Types::Script.new(code_hash: Settings.sudt_cell_type_hash, args: issuer_address.lock_hash, hash_type: "type") - node_block.transactions.first.outputs_data[0] = "0x000050ad321ea12e0000000000000000" + node_block.transactions.first.outputs_data[0] = + "0x000050ad321ea12e0000000000000000" create(:udt, code_hash: Settings.sudt_cell_type_hash, type_hash: node_output.type.compute_hash, block_timestamp: node_block.header.timestamp) node_data_processor.process_block(node_block) @@ -1991,12 +2183,14 @@ class NodeDataProcessorTest < ActiveSupport::TestCase CkbSync::Api.any_instance.stubs(:get_tip_block_number).returns(22) VCR.use_cassette("blocks/21") do node_block = CkbSync::Api.instance.get_block_by_number(21) - create(:block, :with_block_hash, number: node_block.header.number - 1, timestamp: 1557282351075) + create(:block, :with_block_hash, number: node_block.header.number - 1, + timestamp: 1557282351075) node_output = node_block.transactions.first.outputs.first node_output.type = CKB::Types::Script.new(code_hash: CkbSync::Api.instance.token_script_code_hash, args: "0x9cf6ef96c3f053f6d128903e608516d658cac2da0000000000000001", hash_type: "type") - node_block.transactions.first.outputs_data[0] = "0x000050ad321ea12e0000000000000000" + node_block.transactions.first.outputs_data[0] = + "0x000050ad321ea12e0000000000000000" node_data_processor.process_block(node_block) block = Block.find_by(number: 21) block.update(block_hash: "0x419c632366c8eb9635acbb39ea085f7552ae62e1fdd480893375334a0f37d1bx") @@ -2005,7 +2199,9 @@ class NodeDataProcessorTest < ActiveSupport::TestCase end VCR.use_cassette("blocks/22") do - assert_difference -> { address.reload.udt_accounts.m_nft_token.count }, -1 do + assert_difference -> { + address.reload.udt_accounts.m_nft_token.count + }, -1 do node_data_processor.call end end @@ -2018,7 +2214,8 @@ class NodeDataProcessorTest < ActiveSupport::TestCase CkbSync::Api.any_instance.stubs(:get_tip_block_number).returns(22) VCR.use_cassette("blocks/21") do node_block = CkbSync::Api.instance.get_block_by_number(21) - create(:block, :with_block_hash, number: node_block.header.number - 1, timestamp: 1557282351075) + create(:block, :with_block_hash, number: node_block.header.number - 1, + timestamp: 1557282351075) node_output = node_block.transactions.first.outputs.first new_node_output = node_output.dup @@ -2027,8 +2224,10 @@ class NodeDataProcessorTest < ActiveSupport::TestCase args: issuer_address1.lock_hash, hash_type: "type") node_output.type = CKB::Types::Script.new(code_hash: Settings.sudt_cell_type_hash, args: issuer_address2.lock_hash, hash_type: "type") - node_block.transactions.first.outputs_data[0] = "0x000050ad321ea12e0000000000000000" - node_block.transactions.first.outputs_data[1] = "0x0000909dceda82370000000000000000" + node_block.transactions.first.outputs_data[0] = + "0x000050ad321ea12e0000000000000000" + node_block.transactions.first.outputs_data[1] = + "0x0000909dceda82370000000000000000" create(:udt, code_hash: Settings.sudt_cell_type_hash, type_hash: node_output.type.compute_hash, block_timestamp: node_block.header.timestamp) create(:udt, code_hash: Settings.sudt_cell_type_hash, type_hash: new_node_output.type.compute_hash, @@ -2042,7 +2241,9 @@ class NodeDataProcessorTest < ActiveSupport::TestCase VCR.use_cassette("blocks/22") do old_total_amount = CkbUtils.parse_udt_cell_data("0x000050ad321ea12e0000000000000000") + CkbUtils.parse_udt_cell_data("0x0000909dceda82370000000000000000") - assert_changes -> { address.reload.udt_accounts.sum(:amount) }, from: old_total_amount, to: 0 do + assert_changes -> { + address.reload.udt_accounts.sum(:amount) + }, from: old_total_amount, to: 0 do node_data_processor.call end end @@ -2052,7 +2253,8 @@ class NodeDataProcessorTest < ActiveSupport::TestCase issuer_address = create(:address) udt_type_script = CKB::Types::Script.new(code_hash: Settings.sudt_cell_type_hash, args: issuer_address.lock_hash, hash_type: "type") - create(:udt, code_hash: Settings.sudt_cell_type_hash, type_hash: udt_type_script.compute_hash) + create(:udt, code_hash: Settings.sudt_cell_type_hash, + type_hash: udt_type_script.compute_hash) block = create(:block, :with_block_hash) previous_cell_output_lock_script = create(:lock_script, code_hash: Settings.secp_cell_type_hash, args: "0xb2e61ff569acf041b3c2c17724e2379c581eeac3", hash_type: "type") @@ -2060,14 +2262,15 @@ class NodeDataProcessorTest < ActiveSupport::TestCase udt_lock_script = CKB::Types::Script.new(code_hash: Settings.secp_cell_type_hash, args: "0x3954acece65096bfa81258983ddb83915fc56bd8", hash_type: "type") udt_amount = 1000000 - create(:udt_account, address: address, amount: udt_amount, type_hash: udt_type_script.compute_hash) - previous_ckb_transaction = create(:ckb_transaction, address: address) + create(:udt_account, address:, amount: udt_amount, + type_hash: udt_type_script.compute_hash) + previous_ckb_transaction = create(:ckb_transaction, address:) previous_cell_output = create(:cell_output, ckb_transaction: previous_ckb_transaction, - block: block, + block:, cell_type: "udt", - address: address, - udt_amount: udt_amount, + address:, + udt_amount:, cell_index: 0, tx_hash: previous_ckb_transaction.tx_hash, capacity: 300 * 10**8, @@ -2082,7 +2285,8 @@ class NodeDataProcessorTest < ActiveSupport::TestCase create(:block, :with_block_hash, number: node_block.header.number - 1) input = CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: previous_cell_output.tx_hash, index: 0)) - output = CKB::Types::Output.new(capacity: 150 * 10**8, lock: udt_lock_script, type: udt_type_script) + output = CKB::Types::Output.new(capacity: 150 * 10**8, + lock: udt_lock_script, type: udt_type_script) tx = CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", inputs: [input], outputs: [output], outputs_data: ["0x000050ad321ea12e0000000000000000"]) node_block.transactions << tx @@ -2098,16 +2302,19 @@ class NodeDataProcessorTest < ActiveSupport::TestCase node_data_processor.process_block(node_block) end - assert_equal 0, address.udt_accounts.find_by(type_hash: udt_type_script.compute_hash).amount + assert_equal 0, + address.udt_accounts.find_by(type_hash: udt_type_script.compute_hash).amount assert_equal 0, address.reload.balance_occupied assert_equal 150 * 10**8, output_address.reload.balance_occupied end end test "should update tx's contained address ids" do - block1 = create(:block, :with_block_hash, number: DEFAULT_NODE_BLOCK_NUMBER - 2) + block1 = create(:block, :with_block_hash, + number: DEFAULT_NODE_BLOCK_NUMBER - 2) tx1 = create(:ckb_transaction, block: block1) - block2 = create(:block, :with_block_hash, number: DEFAULT_NODE_BLOCK_NUMBER - 1) + block2 = create(:block, :with_block_hash, + number: DEFAULT_NODE_BLOCK_NUMBER - 1) tx2 = create(:ckb_transaction, block: block2) tx3 = create(:ckb_transaction, block: block2) tx4 = create(:ckb_transaction, block: block2) @@ -2131,13 +2338,23 @@ class NodeDataProcessorTest < ActiveSupport::TestCase header = CKB::Types::BlockHeader.new(compact_target: "0x1000", hash: "0x#{SecureRandom.hex(32)}", number: DEFAULT_NODE_BLOCK_NUMBER, parent_hash: "0x#{SecureRandom.hex(32)}", nonce: 1757392074788233522, timestamp: CkbUtils.time_in_milliseconds(Time.current), transactions_root: "0x#{SecureRandom.hex(32)}", proposals_hash: "0x#{SecureRandom.hex(32)}", extra_hash: "0x#{SecureRandom.hex(32)}", version: 0, epoch: 1, dao: "0x01000000000000000000c16ff286230000a3a65e97fd03000057c138586f0000") inputs = [ - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx1.tx_hash, index: 0)), - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx2.tx_hash, index: 1)), - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx3.tx_hash, index: 2)) + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx1.tx_hash, index: 0, + )), + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx2.tx_hash, index: 1, + )), + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx3.tx_hash, index: 2, + )), ] inputs1 = [ - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx4.tx_hash, index: 0)), - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx5.tx_hash, index: 0)) + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx4.tx_hash, index: 0, + )), + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx5.tx_hash, index: 0, + )), ] lock1 = CKB::Types::Script.new(code_hash: Settings.secp_cell_type_hash, hash_type: "type", args: "0x#{SecureRandom.hex(20)}") @@ -2148,34 +2365,35 @@ class NodeDataProcessorTest < ActiveSupport::TestCase outputs = [ CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock1), CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock2), - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock3) + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock3), ] outputs1 = [ CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock1), CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock2), - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock3) + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock3), ] miner_lock = CKB::Types::Script.new(code_hash: Settings.secp_cell_type_hash, hash_type: "type", args: "0x#{SecureRandom.hex(20)}") cellbase_inputs = [ CKB::Types::Input.new( previous_output: CKB::Types::OutPoint.new( - tx_hash: "0x0000000000000000000000000000000000000000000000000000000000000000", index: 4294967295 + tx_hash: "0x0000000000000000000000000000000000000000000000000000000000000000", index: 4294967295, ), since: 3000 - ) + ), ] cellbase_outputs = [ - CKB::Types::Output.new(capacity: 200986682127, lock: miner_lock) + CKB::Types::Output.new(capacity: 200986682127, lock: miner_lock), ] transactions = [ CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs: cellbase_inputs, outputs: cellbase_outputs, outputs_data: %w[0x], witnesses: ["0x590000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd800000000"]), - CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs: inputs, - outputs: outputs, outputs_data: %w[0x 0x 0x], witnesses: ["0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000"]), + CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs:, + outputs:, outputs_data: %w[0x 0x 0x], witnesses: ["0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000"]), CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs: inputs1, - outputs: outputs1, outputs_data: %w[0x 0x 0x], witnesses: ["0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000"]) + outputs: outputs1, outputs_data: %w[0x 0x 0x], witnesses: ["0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000"]), ] - node_block = CKB::Types::Block.new(uncles: [], proposals: [], transactions: transactions, header: header) + node_block = CKB::Types::Block.new(uncles: [], proposals: [], + transactions:, header:) block = node_data_processor.process_block(node_block) address1 = Address.find_by(lock_hash: lock1.compute_hash) @@ -2190,9 +2408,11 @@ class NodeDataProcessorTest < ActiveSupport::TestCase end test "should update tx's tags when output have nervos_dao_deposit cells" do - block1 = create(:block, :with_block_hash, number: DEFAULT_NODE_BLOCK_NUMBER - 2) + block1 = create(:block, :with_block_hash, + number: DEFAULT_NODE_BLOCK_NUMBER - 2) tx1 = create(:ckb_transaction, block: block1) - block2 = create(:block, :with_block_hash, number: DEFAULT_NODE_BLOCK_NUMBER - 1) + block2 = create(:block, :with_block_hash, + number: DEFAULT_NODE_BLOCK_NUMBER - 1) tx2 = create(:ckb_transaction, block: block2) tx3 = create(:ckb_transaction, block: block2) tx4 = create(:ckb_transaction, block: block2) @@ -2215,13 +2435,23 @@ class NodeDataProcessorTest < ActiveSupport::TestCase header = CKB::Types::BlockHeader.new(compact_target: "0x1000", hash: "0x#{SecureRandom.hex(32)}", number: DEFAULT_NODE_BLOCK_NUMBER, parent_hash: "0x#{SecureRandom.hex(32)}", nonce: 1757392074788233522, timestamp: CkbUtils.time_in_milliseconds(Time.current), transactions_root: "0x#{SecureRandom.hex(32)}", proposals_hash: "0x#{SecureRandom.hex(32)}", extra_hash: "0x#{SecureRandom.hex(32)}", version: 0, epoch: 1, dao: "0x01000000000000000000c16ff286230000a3a65e97fd03000057c138586f0000") inputs = [ - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx1.tx_hash, index: 0)), - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx2.tx_hash, index: 1)), - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx3.tx_hash, index: 2)) + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx1.tx_hash, index: 0, + )), + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx2.tx_hash, index: 1, + )), + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx3.tx_hash, index: 2, + )), ] inputs1 = [ - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx4.tx_hash, index: 0)), - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx5.tx_hash, index: 0)) + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx4.tx_hash, index: 0, + )), + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx5.tx_hash, index: 0, + )), ] lock1 = CKB::Types::Script.new(code_hash: Settings.secp_cell_type_hash, hash_type: "type", args: "0x#{SecureRandom.hex(20)}") @@ -2229,38 +2459,44 @@ class NodeDataProcessorTest < ActiveSupport::TestCase args: "0x#{SecureRandom.hex(20)}") lock3 = CKB::Types::Script.new(code_hash: Settings.secp_cell_type_hash, hash_type: "type", args: "0x#{SecureRandom.hex(20)}") - dao_type = CKB::Types::Script.new(code_hash: Settings.dao_type_hash, hash_type: "type", args: "0x") + dao_type = CKB::Types::Script.new(code_hash: Settings.dao_type_hash, + hash_type: "type", args: "0x") outputs = [ - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock1, type: dao_type), - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock2, type: dao_type), - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock3) + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock1, + type: dao_type), + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock2, + type: dao_type), + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock3), ] outputs1 = [ - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock1, type: dao_type), - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock2, type: dao_type), - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock3) + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock1, + type: dao_type), + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock2, + type: dao_type), + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock3), ] miner_lock = CKB::Types::Script.new(code_hash: Settings.secp_cell_type_hash, hash_type: "type", args: "0x#{SecureRandom.hex(20)}") cellbase_inputs = [ CKB::Types::Input.new( previous_output: CKB::Types::OutPoint.new( - tx_hash: "0x0000000000000000000000000000000000000000000000000000000000000000", index: 4294967295 + tx_hash: "0x0000000000000000000000000000000000000000000000000000000000000000", index: 4294967295, ), since: 3000 - ) + ), ] cellbase_outputs = [ - CKB::Types::Output.new(capacity: 200986682127, lock: miner_lock) + CKB::Types::Output.new(capacity: 200986682127, lock: miner_lock), ] transactions = [ CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs: cellbase_inputs, outputs: cellbase_outputs, outputs_data: %w[0x], witnesses: ["0x590000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd800000000"]), - CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs: inputs, - outputs: outputs, outputs_data: %w[0x0000000000000000 0x0000000000000000 0x], witnesses: ["0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000"]), + CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs:, + outputs:, outputs_data: %w[0x0000000000000000 0x0000000000000000 0x], witnesses: ["0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000"]), CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs: inputs1, - outputs: outputs1, outputs_data: %w[0x0000000000000000 0x0000000000000000 0x], witnesses: ["0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000"]) + outputs: outputs1, outputs_data: %w[0x0000000000000000 0x0000000000000000 0x], witnesses: ["0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000"]), ] - node_block = CKB::Types::Block.new(uncles: [], proposals: [], transactions: transactions, header: header) + node_block = CKB::Types::Block.new(uncles: [], proposals: [], + transactions:, header:) block = node_data_processor.process_block(node_block) tx = block.ckb_transactions.where(is_cellbase: false).first @@ -2272,9 +2508,11 @@ class NodeDataProcessorTest < ActiveSupport::TestCase end test "should recalculate dao contract ckb_transactions_count when block is invalid and has dao txs" do - block1 = create(:block, :with_block_hash, number: DEFAULT_NODE_BLOCK_NUMBER - 2) + block1 = create(:block, :with_block_hash, + number: DEFAULT_NODE_BLOCK_NUMBER - 2) tx1 = create(:ckb_transaction, block: block1) - block2 = create(:block, :with_block_hash, number: DEFAULT_NODE_BLOCK_NUMBER - 1) + block2 = create(:block, :with_block_hash, + number: DEFAULT_NODE_BLOCK_NUMBER - 1) tx2 = create(:ckb_transaction, block: block2) tx3 = create(:ckb_transaction, block: block2) tx4 = create(:ckb_transaction, block: block2) @@ -2297,13 +2535,23 @@ class NodeDataProcessorTest < ActiveSupport::TestCase header = CKB::Types::BlockHeader.new(compact_target: "0x1000", hash: "0x#{SecureRandom.hex(32)}", number: DEFAULT_NODE_BLOCK_NUMBER, parent_hash: "0x#{SecureRandom.hex(32)}", nonce: 1757392074788233522, timestamp: CkbUtils.time_in_milliseconds(Time.current), transactions_root: "0x#{SecureRandom.hex(32)}", proposals_hash: "0x#{SecureRandom.hex(32)}", extra_hash: "0x#{SecureRandom.hex(32)}", version: 0, epoch: 1, dao: "0x01000000000000000000c16ff286230000a3a65e97fd03000057c138586f0000") inputs = [ - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx1.tx_hash, index: 0)), - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx2.tx_hash, index: 1)), - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx3.tx_hash, index: 2)) + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx1.tx_hash, index: 0, + )), + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx2.tx_hash, index: 1, + )), + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx3.tx_hash, index: 2, + )), ] inputs1 = [ - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx4.tx_hash, index: 0)), - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx5.tx_hash, index: 0)) + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx4.tx_hash, index: 0, + )), + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx5.tx_hash, index: 0, + )), ] lock1 = CKB::Types::Script.new(code_hash: Settings.secp_cell_type_hash, hash_type: "type", args: "0x#{SecureRandom.hex(20)}") @@ -2311,52 +2559,63 @@ class NodeDataProcessorTest < ActiveSupport::TestCase args: "0x#{SecureRandom.hex(20)}") lock3 = CKB::Types::Script.new(code_hash: Settings.secp_cell_type_hash, hash_type: "type", args: "0x#{SecureRandom.hex(20)}") - dao_type = CKB::Types::Script.new(code_hash: Settings.dao_type_hash, hash_type: "type", args: "0x") + dao_type = CKB::Types::Script.new(code_hash: Settings.dao_type_hash, + hash_type: "type", args: "0x") outputs = [ - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock1, type: dao_type), - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock2, type: dao_type), - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock3) + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock1, + type: dao_type), + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock2, + type: dao_type), + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock3), ] outputs1 = [ - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock1, type: dao_type), - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock2, type: dao_type), - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock3) + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock1, + type: dao_type), + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock2, + type: dao_type), + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock3), ] miner_lock = CKB::Types::Script.new(code_hash: Settings.secp_cell_type_hash, hash_type: "type", args: "0x#{SecureRandom.hex(20)}") cellbase_inputs = [ CKB::Types::Input.new( previous_output: CKB::Types::OutPoint.new( - tx_hash: "0x0000000000000000000000000000000000000000000000000000000000000000", index: 4294967295 + tx_hash: "0x0000000000000000000000000000000000000000000000000000000000000000", index: 4294967295, ), since: 3000 - ) + ), ] cellbase_outputs = [ - CKB::Types::Output.new(capacity: 200986682127, lock: miner_lock) + CKB::Types::Output.new(capacity: 200986682127, lock: miner_lock), ] transactions = [ CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs: cellbase_inputs, outputs: cellbase_outputs, outputs_data: %w[0x], witnesses: ["0x590000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd800000000"]), - CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs: inputs, - outputs: outputs, outputs_data: %w[0x0000000000000000 0x0000000000000000 0x], witnesses: ["0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000"]), + CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs:, + outputs:, outputs_data: %w[0x0000000000000000 0x0000000000000000 0x], witnesses: ["0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000"]), CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs: inputs1, - outputs: outputs1, outputs_data: %w[0x0000000000000000 0x0000000000000000 0x], witnesses: ["0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000"]) + outputs: outputs1, outputs_data: %w[0x0000000000000000 0x0000000000000000 0x], witnesses: ["0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000"]), ] - node_block = CKB::Types::Block.new(uncles: [], proposals: [], transactions: transactions, header: header) + node_block = CKB::Types::Block.new(uncles: [], proposals: [], + transactions:, header:) block = node_data_processor.process_block(node_block) CkbSync::Api.any_instance.stubs(:get_tip_block_number).returns(block.number + 1) - VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", record: :new_episodes) do - assert_changes -> { DaoContract.default_contract.ckb_transactions_count }, from: 2, to: 0 do + VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", + record: :new_episodes) do + assert_changes -> { + DaoContract.default_contract.ckb_transactions_count + }, from: 2, to: 0 do node_data_processor.call end end end test "should update tx's tags when output have udt cells" do - block1 = create(:block, :with_block_hash, number: DEFAULT_NODE_BLOCK_NUMBER - 2) + block1 = create(:block, :with_block_hash, + number: DEFAULT_NODE_BLOCK_NUMBER - 2) tx1 = create(:ckb_transaction, block: block1) - block2 = create(:block, :with_block_hash, number: DEFAULT_NODE_BLOCK_NUMBER - 1) + block2 = create(:block, :with_block_hash, + number: DEFAULT_NODE_BLOCK_NUMBER - 1) tx2 = create(:ckb_transaction, block: block2) tx3 = create(:ckb_transaction, block: block2) input_address1 = create(:address) @@ -2372,9 +2631,15 @@ class NodeDataProcessorTest < ActiveSupport::TestCase header = CKB::Types::BlockHeader.new(compact_target: "0x1000", hash: "0x#{SecureRandom.hex(32)}", number: DEFAULT_NODE_BLOCK_NUMBER, parent_hash: "0x#{SecureRandom.hex(32)}", nonce: 1757392074788233522, timestamp: CkbUtils.time_in_milliseconds(Time.current), transactions_root: "0x#{SecureRandom.hex(32)}", proposals_hash: "0x#{SecureRandom.hex(32)}", extra_hash: "0x#{SecureRandom.hex(32)}", version: 0, epoch: 1, dao: "0x01000000000000000000c16ff286230000a3a65e97fd03000057c138586f0000") inputs = [ - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx1.tx_hash, index: 0)), - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx2.tx_hash, index: 1)), - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx3.tx_hash, index: 2)) + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx1.tx_hash, index: 0, + )), + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx2.tx_hash, index: 1, + )), + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx3.tx_hash, index: 2, + )), ] lock1 = CKB::Types::Script.new(code_hash: Settings.secp_cell_type_hash, hash_type: "type", args: "0x#{SecureRandom.hex(20)}") @@ -2384,31 +2649,35 @@ class NodeDataProcessorTest < ActiveSupport::TestCase args: "0x#{SecureRandom.hex(20)}") udt_script = CKB::Types::Script.new(code_hash: Settings.sudt_cell_type_hash, hash_type: "type", args: "0x#{SecureRandom.hex(32)}") - Address.create(lock_hash: udt_script.args, address_hash: "0x#{SecureRandom.hex(32)}") + Address.create(lock_hash: udt_script.args, + address_hash: "0x#{SecureRandom.hex(32)}") outputs = [ - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock1, type: udt_script), - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock2, type: udt_script), - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock3) + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock1, + type: udt_script), + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock2, + type: udt_script), + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock3), ] miner_lock = CKB::Types::Script.new(code_hash: Settings.secp_cell_type_hash, hash_type: "type", args: "0x#{SecureRandom.hex(20)}") cellbase_inputs = [ CKB::Types::Input.new( previous_output: CKB::Types::OutPoint.new( - tx_hash: "0x0000000000000000000000000000000000000000000000000000000000000000", index: 4294967295 + tx_hash: "0x0000000000000000000000000000000000000000000000000000000000000000", index: 4294967295, ), since: 3000 - ) + ), ] cellbase_outputs = [ - CKB::Types::Output.new(capacity: 200986682127, lock: miner_lock) + CKB::Types::Output.new(capacity: 200986682127, lock: miner_lock), ] transactions = [ CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs: cellbase_inputs, outputs: cellbase_outputs, outputs_data: %w[0x], witnesses: ["0x590000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd800000000"]), - CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs: inputs, - outputs: outputs, outputs_data: %W[#{CKB::Utils.generate_sudt_amount(1000)} #{CKB::Utils.generate_sudt_amount(1000)} 0x], witnesses: ["0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000"]) + CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs:, + outputs:, outputs_data: %W[#{CKB::Utils.generate_sudt_amount(1000)} #{CKB::Utils.generate_sudt_amount(1000)} 0x], witnesses: ["0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000"]), ] - node_block = CKB::Types::Block.new(uncles: [], proposals: [], transactions: transactions, header: header) + node_block = CKB::Types::Block.new(uncles: [], proposals: [], + transactions:, header:) block = node_data_processor.process_block(node_block) tx = block.ckb_transactions.where(is_cellbase: false).first @@ -2417,9 +2686,11 @@ class NodeDataProcessorTest < ActiveSupport::TestCase end test "should update tx's tags when output have udt cells and nervos_dao_deposit cell" do - block1 = create(:block, :with_block_hash, number: DEFAULT_NODE_BLOCK_NUMBER - 2) + block1 = create(:block, :with_block_hash, + number: DEFAULT_NODE_BLOCK_NUMBER - 2) tx1 = create(:ckb_transaction, block: block1) - block2 = create(:block, :with_block_hash, number: DEFAULT_NODE_BLOCK_NUMBER - 1) + block2 = create(:block, :with_block_hash, + number: DEFAULT_NODE_BLOCK_NUMBER - 1) tx2 = create(:ckb_transaction, block: block2) tx3 = create(:ckb_transaction, block: block2) input_address1 = create(:address) @@ -2435,9 +2706,15 @@ class NodeDataProcessorTest < ActiveSupport::TestCase header = CKB::Types::BlockHeader.new(compact_target: "0x1000", hash: "0x#{SecureRandom.hex(32)}", number: DEFAULT_NODE_BLOCK_NUMBER, parent_hash: "0x#{SecureRandom.hex(32)}", nonce: 1757392074788233522, timestamp: CkbUtils.time_in_milliseconds(Time.current), transactions_root: "0x#{SecureRandom.hex(32)}", proposals_hash: "0x#{SecureRandom.hex(32)}", extra_hash: "0x#{SecureRandom.hex(32)}", version: 0, epoch: 1, dao: "0x01000000000000000000c16ff286230000a3a65e97fd03000057c138586f0000") inputs = [ - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx1.tx_hash, index: 0)), - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx2.tx_hash, index: 1)), - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx3.tx_hash, index: 2)) + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx1.tx_hash, index: 0, + )), + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx2.tx_hash, index: 1, + )), + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx3.tx_hash, index: 2, + )), ] lock1 = CKB::Types::Script.new(code_hash: Settings.secp_cell_type_hash, hash_type: "type", args: "0x#{SecureRandom.hex(20)}") @@ -2445,34 +2722,40 @@ class NodeDataProcessorTest < ActiveSupport::TestCase args: "0x#{SecureRandom.hex(20)}") lock3 = CKB::Types::Script.new(code_hash: Settings.secp_cell_type_hash, hash_type: "type", args: "0x#{SecureRandom.hex(20)}") - dao_type = CKB::Types::Script.new(code_hash: Settings.dao_type_hash, hash_type: "type", args: "0x") + dao_type = CKB::Types::Script.new(code_hash: Settings.dao_type_hash, + hash_type: "type", args: "0x") udt_script = CKB::Types::Script.new(code_hash: Settings.sudt_cell_type_hash, hash_type: "type", args: "0x#{SecureRandom.hex(32)}") - Address.create(lock_hash: udt_script.args, address_hash: "0x#{SecureRandom.hex(32)}") + Address.create(lock_hash: udt_script.args, + address_hash: "0x#{SecureRandom.hex(32)}") outputs = [ - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock1, type: dao_type), - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock2, type: dao_type), - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock3, type: udt_script) + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock1, + type: dao_type), + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock2, + type: dao_type), + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock3, + type: udt_script), ] miner_lock = CKB::Types::Script.new(code_hash: Settings.secp_cell_type_hash, hash_type: "type", args: "0x#{SecureRandom.hex(20)}") cellbase_inputs = [ CKB::Types::Input.new( previous_output: CKB::Types::OutPoint.new( - tx_hash: "0x0000000000000000000000000000000000000000000000000000000000000000", index: 4294967295 + tx_hash: "0x0000000000000000000000000000000000000000000000000000000000000000", index: 4294967295, ), since: 3000 - ) + ), ] cellbase_outputs = [ - CKB::Types::Output.new(capacity: 200986682127, lock: miner_lock) + CKB::Types::Output.new(capacity: 200986682127, lock: miner_lock), ] transactions = [ CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs: cellbase_inputs, outputs: cellbase_outputs, outputs_data: %w[0x], witnesses: ["0x590000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd800000000"]), - CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs: inputs, - outputs: outputs, outputs_data: %W[0x0000000000000000 0x0000000000000000 #{CKB::Utils.generate_sudt_amount(1000)}], witnesses: ["0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000"]) + CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs:, + outputs:, outputs_data: %W[0x0000000000000000 0x0000000000000000 #{CKB::Utils.generate_sudt_amount(1000)}], witnesses: ["0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000"]), ] - node_block = CKB::Types::Block.new(uncles: [], proposals: [], transactions: transactions, header: header) + node_block = CKB::Types::Block.new(uncles: [], proposals: [], + transactions:, header:) block = node_data_processor.process_block(node_block) tx = block.ckb_transactions.where(is_cellbase: false).first @@ -2483,9 +2766,11 @@ class NodeDataProcessorTest < ActiveSupport::TestCase test "should update tx's tags when input have udt cells" do DaoContract.default_contract.update(total_deposit: 100000000000000) - block1 = create(:block, :with_block_hash, number: DEFAULT_NODE_BLOCK_NUMBER - 2) + block1 = create(:block, :with_block_hash, + number: DEFAULT_NODE_BLOCK_NUMBER - 2) tx1 = create(:ckb_transaction, block: block1) - block2 = create(:block, :with_block_hash, number: DEFAULT_NODE_BLOCK_NUMBER - 1) + block2 = create(:block, :with_block_hash, + number: DEFAULT_NODE_BLOCK_NUMBER - 1) tx2 = create(:ckb_transaction, block: block2) tx3 = create(:ckb_transaction, block: block2) tx4 = create(:ckb_transaction, block: block2) @@ -2510,10 +2795,12 @@ class NodeDataProcessorTest < ActiveSupport::TestCase args: "0x#{SecureRandom.hex(32)}") udt_script1 = CKB::Types::Script.new(code_hash: Settings.sudt_cell_type_hash, hash_type: "type", args: "0x#{SecureRandom.hex(32)}") - create(:udt, code_hash: Settings.sudt_cell_type_hash, type_hash: udt_script.compute_hash) - create(:udt, code_hash: Settings.sudt_cell_type_hash, type_hash: udt_script1.compute_hash) + create(:udt, code_hash: Settings.sudt_cell_type_hash, + type_hash: udt_script.compute_hash) + create(:udt, code_hash: Settings.sudt_cell_type_hash, + type_hash: udt_script1.compute_hash) - output1 = create(:cell_output, ckb_transaction: tx1, block: block1, capacity: 50000 * 10**8, + output1 = create(:cell_output, ckb_transaction: tx1, block: block1, capacity: 50000 * 10**8, tx_hash: tx1.tx_hash, cell_index: 0, address: input_address1, cell_type: "udt", lock_script_id: lock1.id, type_hash: udt_script.compute_hash) output2 = create(:cell_output, ckb_transaction: tx2, block: block2, capacity: 60000 * 10**8, tx_hash: tx2.tx_hash, cell_index: 1, address: input_address2, cell_type: "udt", lock_script_id: lock2.id, type_hash: udt_script.compute_hash) @@ -2534,19 +2821,31 @@ class NodeDataProcessorTest < ActiveSupport::TestCase cell_output: output4) create(:type_script, args: udt_script1.args, code_hash: Settings.sudt_cell_type_hash, hash_type: "data", cell_output: output5) - Address.create(lock_hash: udt_script.args, address_hash: "0x#{SecureRandom.hex(32)}") - Address.create(lock_hash: udt_script1.args, address_hash: "0x#{SecureRandom.hex(32)}") + Address.create(lock_hash: udt_script.args, + address_hash: "0x#{SecureRandom.hex(32)}") + Address.create(lock_hash: udt_script1.args, + address_hash: "0x#{SecureRandom.hex(32)}") header = CKB::Types::BlockHeader.new(compact_target: "0x1000", hash: "0x#{SecureRandom.hex(32)}", number: DEFAULT_NODE_BLOCK_NUMBER, parent_hash: "0x#{SecureRandom.hex(32)}", nonce: 1757392074788233522, timestamp: CkbUtils.time_in_milliseconds(Time.current), transactions_root: "0x#{SecureRandom.hex(32)}", proposals_hash: "0x#{SecureRandom.hex(32)}", extra_hash: "0x#{SecureRandom.hex(32)}", version: 0, epoch: 1, dao: "0x01000000000000000000c16ff286230000a3a65e97fd03000057c138586f0000") inputs = [ - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx1.tx_hash, index: 0)), - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx2.tx_hash, index: 1)), - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx3.tx_hash, index: 2)) + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx1.tx_hash, index: 0, + )), + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx2.tx_hash, index: 1, + )), + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx3.tx_hash, index: 2, + )), ] inputs1 = [ - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx4.tx_hash, index: 0)), - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx5.tx_hash, index: 0)) + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx4.tx_hash, index: 0, + )), + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx5.tx_hash, index: 0, + )), ] lock1 = CKB::Types::Script.new(code_hash: Settings.secp_cell_type_hash, hash_type: "type", args: "0x#{SecureRandom.hex(20)}") @@ -2558,35 +2857,36 @@ class NodeDataProcessorTest < ActiveSupport::TestCase outputs = [ CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock1), CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock2), - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock3) + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock3), ] outputs1 = [ CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock1), CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock2), - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock3) + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock3), ] miner_lock = CKB::Types::Script.new(code_hash: Settings.secp_cell_type_hash, hash_type: "type", args: "0x#{SecureRandom.hex(20)}") cellbase_inputs = [ CKB::Types::Input.new( previous_output: CKB::Types::OutPoint.new( - tx_hash: "0x0000000000000000000000000000000000000000000000000000000000000000", index: 4294967295 + tx_hash: "0x0000000000000000000000000000000000000000000000000000000000000000", index: 4294967295, ), since: 3000 - ) + ), ] cellbase_outputs = [ - CKB::Types::Output.new(capacity: 200986682127, lock: miner_lock) + CKB::Types::Output.new(capacity: 200986682127, lock: miner_lock), ] transactions = [ CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs: cellbase_inputs, outputs: cellbase_outputs, outputs_data: %w[0x], witnesses: ["0x590000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd800000000"]), - CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs: inputs, - outputs: outputs, outputs_data: %w[0x 0x 0x], witnesses: ["0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000"]), + CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs:, + outputs:, outputs_data: %w[0x 0x 0x], witnesses: ["0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000"]), CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs: inputs1, - outputs: outputs1, outputs_data: %w[0x 0x 0x], witnesses: ["0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000"]) + outputs: outputs1, outputs_data: %w[0x 0x 0x], witnesses: ["0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000"]), ] - node_block = CKB::Types::Block.new(uncles: [], proposals: [], transactions: transactions, header: header) + node_block = CKB::Types::Block.new(uncles: [], proposals: [], + transactions:, header:) block = node_data_processor.process_block(node_block) tx = block.ckb_transactions.where(is_cellbase: false).first @@ -2598,9 +2898,11 @@ class NodeDataProcessorTest < ActiveSupport::TestCase test "should update tx's tags when input have udt cells and nervos_dao_withdrawing cells" do DaoContract.default_contract.update(total_deposit: 100000000000000) - block1 = create(:block, :with_block_hash, number: DEFAULT_NODE_BLOCK_NUMBER - 2) + block1 = create(:block, :with_block_hash, + number: DEFAULT_NODE_BLOCK_NUMBER - 2) tx1 = create(:ckb_transaction, block: block1) - block2 = create(:block, :with_block_hash, number: DEFAULT_NODE_BLOCK_NUMBER - 1) + block2 = create(:block, :with_block_hash, + number: DEFAULT_NODE_BLOCK_NUMBER - 1) deposit_block = create(:block, :with_block_hash, number: DEFAULT_NODE_BLOCK_NUMBER - 5, dao: "0x1c3a5eac4286070025e0edf5ca8823001c957f5b5000000000e3bad4847a0100") @@ -2637,12 +2939,12 @@ class NodeDataProcessorTest < ActiveSupport::TestCase udt_script = CKB::Types::Script.new( code_hash: Settings.sudt_cell_type_hash, hash_type: "type", - args: "0x#{SecureRandom.hex(32)}" + args: "0x#{SecureRandom.hex(32)}", ) udt_script1 = CKB::Types::Script.new( code_hash: Settings.sudt_cell_type_hash, hash_type: "type", - args: "0x#{SecureRandom.hex(32)}" + args: "0x#{SecureRandom.hex(32)}", ) create(:udt, code_hash: Settings.sudt_cell_type_hash, type_hash: udt_script.compute_hash) @@ -2683,19 +2985,19 @@ class NodeDataProcessorTest < ActiveSupport::TestCase block: block1, previous_output: { tx_hash: deposit_tx.tx_hash, - index: 0 + index: 0, }) create(:cell_input, ckb_transaction: tx2, block: block2, previous_output: { tx_hash: deposit_tx.tx_hash, - index: 1 + index: 1, }) create(:cell_input, ckb_transaction: tx2, block: block2, previous_output: { tx_hash: deposit_tx.tx_hash, - index: 2 + index: 2, }) # nervos_dao_withdrawing cells @@ -2752,13 +3054,13 @@ class NodeDataProcessorTest < ActiveSupport::TestCase block: block2, previous_output: { tx_hash: deposit_tx1.tx_hash, - index: 0 + index: 0, }) create(:cell_input, ckb_transaction: tx5, block: block2, previous_output: { tx_hash: deposit_tx1.tx_hash, - index: 1 + index: 1, }) # nervos_dao_withdrawing cell create(:cell_output, ckb_transaction: tx4, @@ -2796,8 +3098,10 @@ class NodeDataProcessorTest < ActiveSupport::TestCase create(:type_script, args: udt_script1.args, code_hash: Settings.sudt_cell_type_hash, hash_type: "data") - Address.create(lock_hash: udt_script.args, address_hash: "0x#{SecureRandom.hex(32)}") - Address.create(lock_hash: udt_script1.args, address_hash: "0x#{SecureRandom.hex(32)}") + Address.create(lock_hash: udt_script.args, + address_hash: "0x#{SecureRandom.hex(32)}") + Address.create(lock_hash: udt_script1.args, + address_hash: "0x#{SecureRandom.hex(32)}") header = CKB::Types::BlockHeader.new( compact_target: "0x1000", @@ -2811,57 +3115,57 @@ class NodeDataProcessorTest < ActiveSupport::TestCase extra_hash: "0x#{SecureRandom.hex(32)}", version: 0, epoch: 1, - dao: "0x01000000000000000000c16ff286230000a3a65e97fd03000057c138586f0000" + dao: "0x01000000000000000000c16ff286230000a3a65e97fd03000057c138586f0000", ) inputs = [ CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx1.tx_hash, index: 0)), # nervos_dao_withdrawing cell CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx2.tx_hash, index: 1)), # nervos_dao_withdrawing cell - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx3.tx_hash, index: 2)) # udt cell + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx3.tx_hash, index: 2)), # udt cell ] inputs1 = [ CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx4.tx_hash, index: 0)), # nervos_dao_withdrawing cell - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx5.tx_hash, index: 0)) # udt cell + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx5.tx_hash, index: 0)), # udt cell ] lock1 = CKB::Types::Script.new( code_hash: Settings.secp_cell_type_hash, hash_type: "type", - args: "0x#{SecureRandom.hex(20)}" + args: "0x#{SecureRandom.hex(20)}", ) lock2 = CKB::Types::Script.new( code_hash: Settings.secp_cell_type_hash, hash_type: "type", - args: "0x#{SecureRandom.hex(20)}" + args: "0x#{SecureRandom.hex(20)}", ) lock3 = CKB::Types::Script.new( code_hash: Settings.secp_cell_type_hash, hash_type: "type", - args: "0x#{SecureRandom.hex(20)}" + args: "0x#{SecureRandom.hex(20)}", ) outputs = [ CKB::Types::Output.new(capacity: 50000 * 10**8, lock: lock1), CKB::Types::Output.new(capacity: 60000 * 10**8, lock: lock2), - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock3) + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock3), ] outputs1 = [ CKB::Types::Output.new(capacity: 50000 * 10**8, lock: lock1), CKB::Types::Output.new(capacity: 60000 * 10**8, lock: lock2), - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock3) + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock3), ] miner_lock = CKB::Types::Script.new( code_hash: Settings.secp_cell_type_hash, hash_type: "type", - args: "0x#{SecureRandom.hex(20)}" + args: "0x#{SecureRandom.hex(20)}", ) cellbase_inputs = [ CKB::Types::Input.new( previous_output: CKB::Types::OutPoint.new( - tx_hash: "0x0000000000000000000000000000000000000000000000000000000000000000", index: 4294967295 + tx_hash: "0x0000000000000000000000000000000000000000000000000000000000000000", index: 4294967295, ), since: 3000 - ) + ), ] cellbase_outputs = [ - CKB::Types::Output.new(capacity: 200986682127, lock: miner_lock) + CKB::Types::Output.new(capacity: 200986682127, lock: miner_lock), ] transactions = [ CKB::Types::Transaction.new( @@ -2872,19 +3176,19 @@ class NodeDataProcessorTest < ActiveSupport::TestCase outputs: cellbase_outputs, outputs_data: %w[0x], witnesses: [ - "0x590000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd800000000" - ] + "0x590000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd800000000", + ], ), CKB::Types::Transaction.new( hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [block1.block_hash], - inputs: inputs, - outputs: outputs, + inputs:, + outputs:, outputs_data: %w[0x 0x 0x], witnesses: [ - "0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000" - ] + "0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000", + ], ), CKB::Types::Transaction.new( hash: "0x#{SecureRandom.hex(32)}", @@ -2894,15 +3198,15 @@ class NodeDataProcessorTest < ActiveSupport::TestCase outputs: outputs1, outputs_data: %w[0x 0x 0x], witnesses: [ - "0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000" - ] - ) + "0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000", + ], + ), ] node_block = CKB::Types::Block.new( uncles: [], proposals: [], - transactions: transactions, - header: header + transactions:, + header:, ) block = node_data_processor.process_block(node_block) @@ -2939,9 +3243,11 @@ class NodeDataProcessorTest < ActiveSupport::TestCase end test "#process_block should update tx's contained_udt_ids when there are udt cells in outputs" do - block1 = create(:block, :with_block_hash, number: DEFAULT_NODE_BLOCK_NUMBER - 2) + block1 = create(:block, :with_block_hash, + number: DEFAULT_NODE_BLOCK_NUMBER - 2) tx1 = create(:ckb_transaction, block: block1) - block2 = create(:block, :with_block_hash, number: DEFAULT_NODE_BLOCK_NUMBER - 1) + block2 = create(:block, :with_block_hash, + number: DEFAULT_NODE_BLOCK_NUMBER - 1) tx2 = create(:ckb_transaction, block: block2) tx3 = create(:ckb_transaction, block: block2) tx4 = create(:ckb_transaction, block: block2) @@ -2965,13 +3271,23 @@ class NodeDataProcessorTest < ActiveSupport::TestCase header = CKB::Types::BlockHeader.new(compact_target: "0x1000", hash: "0x#{SecureRandom.hex(32)}", number: DEFAULT_NODE_BLOCK_NUMBER, parent_hash: "0x#{SecureRandom.hex(32)}", nonce: 1757392074788233522, timestamp: CkbUtils.time_in_milliseconds(Time.current), transactions_root: "0x#{SecureRandom.hex(32)}", proposals_hash: "0x#{SecureRandom.hex(32)}", extra_hash: "0x#{SecureRandom.hex(32)}", version: 0, epoch: 1, dao: "0x01000000000000000000c16ff286230000a3a65e97fd03000057c138586f0000") inputs = [ - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx1.tx_hash, index: 0)), - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx2.tx_hash, index: 1)), - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx3.tx_hash, index: 2)) + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx1.tx_hash, index: 0, + )), + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx2.tx_hash, index: 1, + )), + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx3.tx_hash, index: 2, + )), ] inputs1 = [ - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx4.tx_hash, index: 0)), - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx5.tx_hash, index: 0)) + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx4.tx_hash, index: 0, + )), + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx5.tx_hash, index: 0, + )), ] lock1 = CKB::Types::Script.new(code_hash: Settings.secp_cell_type_hash, hash_type: "type", args: "0x#{SecureRandom.hex(20)}") @@ -2983,40 +3299,48 @@ class NodeDataProcessorTest < ActiveSupport::TestCase args: "0x#{SecureRandom.hex(32)}") udt_script2 = CKB::Types::Script.new(code_hash: Settings.sudt_cell_type_hash, hash_type: "type", args: "0x#{SecureRandom.hex(32)}") - Address.create(lock_hash: udt_script1.args, address_hash: "0x#{SecureRandom.hex(32)}") - Address.create(lock_hash: udt_script2.args, address_hash: "0x#{SecureRandom.hex(32)}") + Address.create(lock_hash: udt_script1.args, + address_hash: "0x#{SecureRandom.hex(32)}") + Address.create(lock_hash: udt_script2.args, + address_hash: "0x#{SecureRandom.hex(32)}") outputs = [ - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock1, type: udt_script1), - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock2, type: udt_script2), - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock3) + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock1, + type: udt_script1), + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock2, + type: udt_script2), + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock3), ] outputs1 = [ - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock1, type: udt_script1), - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock2, type: udt_script2), - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock2, type: udt_script2), - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock3) + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock1, + type: udt_script1), + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock2, + type: udt_script2), + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock2, + type: udt_script2), + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock3), ] miner_lock = CKB::Types::Script.new(code_hash: Settings.secp_cell_type_hash, hash_type: "type", args: "0x#{SecureRandom.hex(20)}") cellbase_inputs = [ CKB::Types::Input.new( previous_output: CKB::Types::OutPoint.new( - tx_hash: "0x0000000000000000000000000000000000000000000000000000000000000000", index: 4294967295 + tx_hash: "0x0000000000000000000000000000000000000000000000000000000000000000", index: 4294967295, ), since: 3000 - ) + ), ] cellbase_outputs = [ - CKB::Types::Output.new(capacity: 200986682127, lock: miner_lock) + CKB::Types::Output.new(capacity: 200986682127, lock: miner_lock), ] transactions = [ CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs: cellbase_inputs, outputs: cellbase_outputs, outputs_data: %w[0x], witnesses: ["0x590000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd800000000"]), - CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs: inputs, - outputs: outputs, outputs_data: %W[#{CKB::Utils.generate_sudt_amount(1000)} #{CKB::Utils.generate_sudt_amount(1000)} 0x], witnesses: ["0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000"]), + CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs:, + outputs:, outputs_data: %W[#{CKB::Utils.generate_sudt_amount(1000)} #{CKB::Utils.generate_sudt_amount(1000)} 0x], witnesses: ["0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000"]), CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs: inputs1, - outputs: outputs1, outputs_data: %W[#{CKB::Utils.generate_sudt_amount(1000)} #{CKB::Utils.generate_sudt_amount(1000)} #{CKB::Utils.generate_sudt_amount(1000)} 0x], witnesses: ["0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000"]) + outputs: outputs1, outputs_data: %W[#{CKB::Utils.generate_sudt_amount(1000)} #{CKB::Utils.generate_sudt_amount(1000)} #{CKB::Utils.generate_sudt_amount(1000)} 0x], witnesses: ["0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000"]), ] - node_block = CKB::Types::Block.new(uncles: [], proposals: [], transactions: transactions, header: header) + node_block = CKB::Types::Block.new(uncles: [], proposals: [], + transactions:, header:) block = node_data_processor.process_block(node_block) udt1 = Udt.find_by(args: udt_script1.args) udt2 = Udt.find_by(args: udt_script2.args) @@ -3042,13 +3366,20 @@ class NodeDataProcessorTest < ActiveSupport::TestCase args: udt_script1.args, ckb_transactions_count: 3) udt2 = create(:udt, type_hash: CKB::Types::Script.new(**type_script2.to_node).compute_hash, args: udt_script2.args, ckb_transactions_count: 2) - block1 = create(:block, :with_block_hash, number: DEFAULT_NODE_BLOCK_NUMBER - 2) - tx1 = create(:ckb_transaction, block: block1, contained_udt_ids: [udt1.id]) - block2 = create(:block, :with_block_hash, number: DEFAULT_NODE_BLOCK_NUMBER - 1) - tx2 = create(:ckb_transaction, block: block2, contained_udt_ids: [udt2.id]) - tx3 = create(:ckb_transaction, block: block2, contained_udt_ids: [udt1.id]) - tx4 = create(:ckb_transaction, block: block2, contained_udt_ids: [udt1.id]) - tx5 = create(:ckb_transaction, block: block2, contained_udt_ids: [udt2.id]) + block1 = create(:block, :with_block_hash, + number: DEFAULT_NODE_BLOCK_NUMBER - 2) + tx1 = create(:ckb_transaction, block: block1, + contained_udt_ids: [udt1.id]) + block2 = create(:block, :with_block_hash, + number: DEFAULT_NODE_BLOCK_NUMBER - 1) + tx2 = create(:ckb_transaction, block: block2, + contained_udt_ids: [udt2.id]) + tx3 = create(:ckb_transaction, block: block2, + contained_udt_ids: [udt1.id]) + tx4 = create(:ckb_transaction, block: block2, + contained_udt_ids: [udt1.id]) + tx5 = create(:ckb_transaction, block: block2, + contained_udt_ids: [udt2.id]) input_address1 = create(:address) input_address2 = create(:address) input_address3 = create(:address) @@ -3086,19 +3417,31 @@ class NodeDataProcessorTest < ActiveSupport::TestCase output3.update(type_hash: CKB::Types::Script.new(**output3.type_script.to_node).compute_hash) output4.update(type_hash: CKB::Types::Script.new(**output4.type_script.to_node).compute_hash) output5.update(type_hash: CKB::Types::Script.new(**output5.type_script.to_node).compute_hash) - Address.create(lock_hash: udt_script1.args, address_hash: "0x#{SecureRandom.hex(32)}") - Address.create(lock_hash: udt_script2.args, address_hash: "0x#{SecureRandom.hex(32)}") + Address.create(lock_hash: udt_script1.args, + address_hash: "0x#{SecureRandom.hex(32)}") + Address.create(lock_hash: udt_script2.args, + address_hash: "0x#{SecureRandom.hex(32)}") header = CKB::Types::BlockHeader.new(compact_target: "0x1000", hash: "0x#{SecureRandom.hex(32)}", number: DEFAULT_NODE_BLOCK_NUMBER, parent_hash: "0x#{SecureRandom.hex(32)}", nonce: 1757392074788233522, timestamp: CkbUtils.time_in_milliseconds(Time.current), transactions_root: "0x#{SecureRandom.hex(32)}", proposals_hash: "0x#{SecureRandom.hex(32)}", extra_hash: "0x#{SecureRandom.hex(32)}", version: 0, epoch: 1, dao: "0x01000000000000000000c16ff286230000a3a65e97fd03000057c138586f0000") inputs = [ - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx1.tx_hash, index: 0)), - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx2.tx_hash, index: 1)), - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx3.tx_hash, index: 2)) + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx1.tx_hash, index: 0, + )), + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx2.tx_hash, index: 1, + )), + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx3.tx_hash, index: 2, + )), ] inputs1 = [ - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx4.tx_hash, index: 0)), - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx5.tx_hash, index: 0)) + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx4.tx_hash, index: 0, + )), + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx5.tx_hash, index: 0, + )), ] lock1 = CKB::Types::Script.new(code_hash: Settings.secp_cell_type_hash, hash_type: "type", args: "0x#{SecureRandom.hex(20)}") @@ -3110,29 +3453,30 @@ class NodeDataProcessorTest < ActiveSupport::TestCase outputs = [ CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock1), CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock2), - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock3) + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock3), ] miner_lock = CKB::Types::Script.new(code_hash: Settings.secp_cell_type_hash, hash_type: "type", args: "0x#{SecureRandom.hex(20)}") cellbase_inputs = [ CKB::Types::Input.new( previous_output: CKB::Types::OutPoint.new( - tx_hash: "0x0000000000000000000000000000000000000000000000000000000000000000", index: 4294967295 + tx_hash: "0x0000000000000000000000000000000000000000000000000000000000000000", index: 4294967295, ), since: 3000 - ) + ), ] cellbase_outputs = [ - CKB::Types::Output.new(capacity: 200986682127, lock: miner_lock) + CKB::Types::Output.new(capacity: 200986682127, lock: miner_lock), ] transactions = [ CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs: cellbase_inputs, outputs: cellbase_outputs, outputs_data: %w[0x], witnesses: ["0x590000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd800000000"]), - CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs: inputs, - outputs: outputs, outputs_data: %w[0x 0x 0x], witnesses: ["0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000"]), + CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs:, + outputs:, outputs_data: %w[0x 0x 0x], witnesses: ["0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000"]), CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs: inputs1, - outputs: outputs, outputs_data: %w[0x 0x 0x], witnesses: ["0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000"]) + outputs:, outputs_data: %w[0x 0x 0x], witnesses: ["0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000"]), ] - node_block = CKB::Types::Block.new(uncles: [], proposals: [], transactions: transactions, header: header) + node_block = CKB::Types::Block.new(uncles: [], proposals: [], + transactions:, header:) block = node_data_processor.process_block(node_block) udt1 = Udt.find_by(args: udt_script1.args) udt2 = Udt.find_by(args: udt_script2.args) @@ -3147,9 +3491,11 @@ class NodeDataProcessorTest < ActiveSupport::TestCase end test "should recalculate udts ckb transactions count when block is invalid and outputs has udt cell" do - block1 = create(:block, :with_block_hash, number: DEFAULT_NODE_BLOCK_NUMBER - 2) + block1 = create(:block, :with_block_hash, + number: DEFAULT_NODE_BLOCK_NUMBER - 2) tx1 = create(:ckb_transaction, block: block1) - block2 = create(:block, :with_block_hash, number: DEFAULT_NODE_BLOCK_NUMBER - 1) + block2 = create(:block, :with_block_hash, + number: DEFAULT_NODE_BLOCK_NUMBER - 1) tx2 = create(:ckb_transaction, block: block2) tx3 = create(:ckb_transaction, block: block2) tx4 = create(:ckb_transaction, block: block2) @@ -3172,13 +3518,23 @@ class NodeDataProcessorTest < ActiveSupport::TestCase header = CKB::Types::BlockHeader.new(compact_target: "0x1000", hash: "0x#{SecureRandom.hex(32)}", number: DEFAULT_NODE_BLOCK_NUMBER, parent_hash: "0x#{SecureRandom.hex(32)}", nonce: 1757392074788233522, timestamp: CkbUtils.time_in_milliseconds(Time.current), transactions_root: "0x#{SecureRandom.hex(32)}", proposals_hash: "0x#{SecureRandom.hex(32)}", extra_hash: "0x#{SecureRandom.hex(32)}", version: 0, epoch: 1, dao: "0x01000000000000000000c16ff286230000a3a65e97fd03000057c138586f0000") inputs = [ - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx1.tx_hash, index: 0)), - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx2.tx_hash, index: 1)), - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx3.tx_hash, index: 2)) + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx1.tx_hash, index: 0, + )), + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx2.tx_hash, index: 1, + )), + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx3.tx_hash, index: 2, + )), ] inputs1 = [ - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx4.tx_hash, index: 0)), - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx5.tx_hash, index: 0)) + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx4.tx_hash, index: 0, + )), + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx5.tx_hash, index: 0, + )), ] lock1 = CKB::Types::Script.new(code_hash: Settings.secp_cell_type_hash, hash_type: "type", args: "0x#{SecureRandom.hex(20)}") @@ -3190,43 +3546,52 @@ class NodeDataProcessorTest < ActiveSupport::TestCase args: "0x#{SecureRandom.hex(32)}") udt_script2 = CKB::Types::Script.new(code_hash: Settings.sudt_cell_type_hash, hash_type: "type", args: "0x#{SecureRandom.hex(32)}") - Address.create(lock_hash: udt_script1.args, address_hash: "0x#{SecureRandom.hex(32)}") - Address.create(lock_hash: udt_script2.args, address_hash: "0x#{SecureRandom.hex(32)}") + Address.create(lock_hash: udt_script1.args, + address_hash: "0x#{SecureRandom.hex(32)}") + Address.create(lock_hash: udt_script2.args, + address_hash: "0x#{SecureRandom.hex(32)}") outputs = [ - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock1, type: udt_script1), - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock2, type: udt_script2), - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock3) + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock1, + type: udt_script1), + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock2, + type: udt_script2), + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock3), ] outputs1 = [ - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock1, type: udt_script1), - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock2, type: udt_script2), - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock2, type: udt_script2), - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock3) + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock1, + type: udt_script1), + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock2, + type: udt_script2), + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock2, + type: udt_script2), + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock3), ] miner_lock = CKB::Types::Script.new(code_hash: Settings.secp_cell_type_hash, hash_type: "type", args: "0x#{SecureRandom.hex(20)}") cellbase_inputs = [ CKB::Types::Input.new( previous_output: CKB::Types::OutPoint.new( - tx_hash: "0x0000000000000000000000000000000000000000000000000000000000000000", index: 4294967295 + tx_hash: "0x0000000000000000000000000000000000000000000000000000000000000000", index: 4294967295, ), since: 3000 - ) + ), ] cellbase_outputs = [ - CKB::Types::Output.new(capacity: 200986682127, lock: miner_lock) + CKB::Types::Output.new(capacity: 200986682127, lock: miner_lock), ] transactions = [ CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs: cellbase_inputs, outputs: cellbase_outputs, outputs_data: %w[0x], witnesses: ["0x590000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd800000000"]), - CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs: inputs, - outputs: outputs, outputs_data: %W[#{CKB::Utils.generate_sudt_amount(1000)} #{CKB::Utils.generate_sudt_amount(1000)} 0x], witnesses: ["0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000"]), + CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs:, + outputs:, outputs_data: %W[#{CKB::Utils.generate_sudt_amount(1000)} #{CKB::Utils.generate_sudt_amount(1000)} 0x], witnesses: ["0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000"]), CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs: inputs1, - outputs: outputs1, outputs_data: %W[#{CKB::Utils.generate_sudt_amount(1000)} #{CKB::Utils.generate_sudt_amount(1000)} #{CKB::Utils.generate_sudt_amount(1000)} 0x], witnesses: ["0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000"]) + outputs: outputs1, outputs_data: %W[#{CKB::Utils.generate_sudt_amount(1000)} #{CKB::Utils.generate_sudt_amount(1000)} #{CKB::Utils.generate_sudt_amount(1000)} 0x], witnesses: ["0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000"]), ] - node_block = CKB::Types::Block.new(uncles: [], proposals: [], transactions: transactions, header: header) + node_block = CKB::Types::Block.new(uncles: [], proposals: [], + transactions:, header:) block = node_data_processor.process_block(node_block) CkbSync::Api.any_instance.stubs(:get_tip_block_number).returns(block.number + 1) - VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", record: :new_episodes) do + VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", + record: :new_episodes) do node_data_processor.call end @@ -3256,13 +3621,20 @@ class NodeDataProcessorTest < ActiveSupport::TestCase args: udt_script1.args, ckb_transactions_count: 3) udt2 = create(:udt, type_hash: CKB::Types::Script.new(**type_script2.to_node).compute_hash, args: udt_script2.args, ckb_transactions_count: 2) - block1 = create(:block, :with_block_hash, number: DEFAULT_NODE_BLOCK_NUMBER - 2) - tx1 = create(:ckb_transaction, block: block1, contained_udt_ids: [udt1.id]) - block2 = create(:block, :with_block_hash, number: DEFAULT_NODE_BLOCK_NUMBER - 1) - tx2 = create(:ckb_transaction, block: block2, contained_udt_ids: [udt2.id]) - tx3 = create(:ckb_transaction, block: block2, contained_udt_ids: [udt1.id]) - tx4 = create(:ckb_transaction, block: block2, contained_udt_ids: [udt1.id]) - tx5 = create(:ckb_transaction, block: block2, contained_udt_ids: [udt2.id]) + block1 = create(:block, :with_block_hash, + number: DEFAULT_NODE_BLOCK_NUMBER - 2) + tx1 = create(:ckb_transaction, block: block1, + contained_udt_ids: [udt1.id]) + block2 = create(:block, :with_block_hash, + number: DEFAULT_NODE_BLOCK_NUMBER - 1) + tx2 = create(:ckb_transaction, block: block2, + contained_udt_ids: [udt2.id]) + tx3 = create(:ckb_transaction, block: block2, + contained_udt_ids: [udt1.id]) + tx4 = create(:ckb_transaction, block: block2, + contained_udt_ids: [udt1.id]) + tx5 = create(:ckb_transaction, block: block2, + contained_udt_ids: [udt2.id]) input_address1 = create(:address, balance: 50000 * 10**8) input_address2 = create(:address, balance: 60000 * 10**8) input_address3 = create(:address, balance: 70000 * 10**8) @@ -3294,19 +3666,31 @@ class NodeDataProcessorTest < ActiveSupport::TestCase output3.update(type_hash: CKB::Types::Script.new(**output3.type_script.to_node).compute_hash) output4.update(type_hash: CKB::Types::Script.new(**output4.type_script.to_node).compute_hash) output5.update(type_hash: CKB::Types::Script.new(**output5.type_script.to_node).compute_hash) - Address.create(lock_hash: udt_script1.args, address_hash: "0x#{SecureRandom.hex(32)}") - Address.create(lock_hash: udt_script2.args, address_hash: "0x#{SecureRandom.hex(32)}") + Address.create(lock_hash: udt_script1.args, + address_hash: "0x#{SecureRandom.hex(32)}") + Address.create(lock_hash: udt_script2.args, + address_hash: "0x#{SecureRandom.hex(32)}") header = CKB::Types::BlockHeader.new(compact_target: "0x1000", hash: "0x#{SecureRandom.hex(32)}", number: DEFAULT_NODE_BLOCK_NUMBER, parent_hash: "0x#{SecureRandom.hex(32)}", nonce: 1757392074788233522, timestamp: CkbUtils.time_in_milliseconds(Time.current), transactions_root: "0x#{SecureRandom.hex(32)}", proposals_hash: "0x#{SecureRandom.hex(32)}", extra_hash: "0x#{SecureRandom.hex(32)}", version: 0, epoch: 1, dao: "0x01000000000000000000c16ff286230000a3a65e97fd03000057c138586f0000") inputs = [ - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx1.tx_hash, index: 0)), - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx2.tx_hash, index: 1)), - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx3.tx_hash, index: 2)) + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx1.tx_hash, index: 0, + )), + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx2.tx_hash, index: 1, + )), + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx3.tx_hash, index: 2, + )), ] inputs1 = [ - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx4.tx_hash, index: 0)), - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx5.tx_hash, index: 0)) + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx4.tx_hash, index: 0, + )), + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx5.tx_hash, index: 0, + )), ] lock1 = CKB::Types::Script.new(code_hash: Settings.secp_cell_type_hash, hash_type: "type", args: "0x#{SecureRandom.hex(20)}") @@ -3318,34 +3702,36 @@ class NodeDataProcessorTest < ActiveSupport::TestCase outputs = [ CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock1), CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock2), - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock3) + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock3), ] miner_lock = CKB::Types::Script.new(code_hash: Settings.secp_cell_type_hash, hash_type: "type", args: "0x#{SecureRandom.hex(20)}") cellbase_inputs = [ CKB::Types::Input.new( previous_output: CKB::Types::OutPoint.new( - tx_hash: "0x0000000000000000000000000000000000000000000000000000000000000000", index: 4294967295 + tx_hash: "0x0000000000000000000000000000000000000000000000000000000000000000", index: 4294967295, ), since: 3000 - ) + ), ] cellbase_outputs = [ - CKB::Types::Output.new(capacity: 200986682127, lock: miner_lock) + CKB::Types::Output.new(capacity: 200986682127, lock: miner_lock), ] transactions = [ CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs: cellbase_inputs, outputs: cellbase_outputs, outputs_data: %w[0x], witnesses: ["0x590000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd800000000"]), - CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs: inputs, - outputs: outputs, outputs_data: %w[0x 0x 0x], witnesses: ["0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000"]), + CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs:, + outputs:, outputs_data: %w[0x 0x 0x], witnesses: ["0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000"]), CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs: inputs1, - outputs: outputs, outputs_data: %w[0x 0x 0x], witnesses: ["0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000"]) + outputs:, outputs_data: %w[0x 0x 0x], witnesses: ["0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000"]), ] - node_block = CKB::Types::Block.new(uncles: [], proposals: [], transactions: transactions, header: header) + node_block = CKB::Types::Block.new(uncles: [], proposals: [], + transactions:, header:) block = node_data_processor.process_block(node_block) udt1 = Udt.find_by(args: udt_script1.args) udt2 = Udt.find_by(args: udt_script2.args) CkbSync::Api.any_instance.stubs(:get_tip_block_number).returns(block.number + 1) - VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", record: :new_episodes) do + VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", + record: :new_episodes) do node_data_processor.call end assert_equal 3, udt1.reload.ckb_transactions_count @@ -3353,9 +3739,11 @@ class NodeDataProcessorTest < ActiveSupport::TestCase end test "should remove block's contained address's tx cache when block is invalid" do - block1 = create(:block, :with_block_hash, number: DEFAULT_NODE_BLOCK_NUMBER - 2) + block1 = create(:block, :with_block_hash, + number: DEFAULT_NODE_BLOCK_NUMBER - 2) tx1 = create(:ckb_transaction, block: block1) - block2 = create(:block, :with_block_hash, number: DEFAULT_NODE_BLOCK_NUMBER - 1) + block2 = create(:block, :with_block_hash, + number: DEFAULT_NODE_BLOCK_NUMBER - 1) tx2 = create(:ckb_transaction, block: block2) tx3 = create(:ckb_transaction, block: block2) tx4 = create(:ckb_transaction, block: block2) @@ -3379,13 +3767,23 @@ class NodeDataProcessorTest < ActiveSupport::TestCase header = CKB::Types::BlockHeader.new(compact_target: "0x1000", hash: "0x#{SecureRandom.hex(32)}", number: DEFAULT_NODE_BLOCK_NUMBER, parent_hash: "0x#{SecureRandom.hex(32)}", nonce: 1757392074788233522, timestamp: CkbUtils.time_in_milliseconds(Time.current), transactions_root: "0x#{SecureRandom.hex(32)}", proposals_hash: "0x#{SecureRandom.hex(32)}", extra_hash: "0x#{SecureRandom.hex(32)}", version: 0, epoch: 1, dao: "0x01000000000000000000c16ff286230000a3a65e97fd03000057c138586f0000") inputs = [ - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx1.tx_hash, index: 0)), - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx2.tx_hash, index: 1)), - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx3.tx_hash, index: 2)) + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx1.tx_hash, index: 0, + )), + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx2.tx_hash, index: 1, + )), + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx3.tx_hash, index: 2, + )), ] inputs1 = [ - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx4.tx_hash, index: 0)), - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx5.tx_hash, index: 0)) + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx4.tx_hash, index: 0, + )), + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx5.tx_hash, index: 0, + )), ] lock1 = CKB::Types::Script.new(code_hash: Settings.secp_cell_type_hash, hash_type: "type", args: "0x#{SecureRandom.hex(20)}") @@ -3393,43 +3791,50 @@ class NodeDataProcessorTest < ActiveSupport::TestCase args: "0x#{SecureRandom.hex(20)}") lock3 = CKB::Types::Script.new(code_hash: Settings.secp_cell_type_hash, hash_type: "type", args: "0x#{SecureRandom.hex(20)}") - dao_type = CKB::Types::Script.new(code_hash: Settings.dao_type_hash, hash_type: "type", args: "0x") + dao_type = CKB::Types::Script.new(code_hash: Settings.dao_type_hash, + hash_type: "type", args: "0x") outputs = [ - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock1, type: dao_type), - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock2, type: dao_type), - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock3) + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock1, + type: dao_type), + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock2, + type: dao_type), + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock3), ] outputs1 = [ - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock1, type: dao_type), - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock2, type: dao_type), - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock3) + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock1, + type: dao_type), + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock2, + type: dao_type), + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock3), ] miner_lock = CKB::Types::Script.new(code_hash: Settings.secp_cell_type_hash, hash_type: "type", args: "0x#{SecureRandom.hex(20)}") cellbase_inputs = [ CKB::Types::Input.new( previous_output: CKB::Types::OutPoint.new( - tx_hash: "0x0000000000000000000000000000000000000000000000000000000000000000", index: 4294967295 + tx_hash: "0x0000000000000000000000000000000000000000000000000000000000000000", index: 4294967295, ), since: 3000 - ) + ), ] cellbase_outputs = [ - CKB::Types::Output.new(capacity: 200986682127, lock: miner_lock) + CKB::Types::Output.new(capacity: 200986682127, lock: miner_lock), ] transactions = [ CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs: cellbase_inputs, outputs: cellbase_outputs, outputs_data: %w[0x], witnesses: ["0x590000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd800000000"]), - CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs: inputs, - outputs: outputs, outputs_data: %w[0x0000000000000000 0x0000000000000000 0x], witnesses: ["0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000"]), + CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs:, + outputs:, outputs_data: %w[0x0000000000000000 0x0000000000000000 0x], witnesses: ["0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000"]), CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs: inputs1, - outputs: outputs1, outputs_data: %w[0x0000000000000000 0x0000000000000000 0x], witnesses: ["0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000"]) + outputs: outputs1, outputs_data: %w[0x0000000000000000 0x0000000000000000 0x], witnesses: ["0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000"]), ] - node_block = CKB::Types::Block.new(uncles: [], proposals: [], transactions: transactions, header: header) + node_block = CKB::Types::Block.new(uncles: [], proposals: [], + transactions:, header:) Sidekiq::Testing.inline! block = node_data_processor.process_block(node_block) CkbSync::Api.any_instance.stubs(:get_tip_block_number).returns(block.number + 1) - VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", record: :new_episodes) do + VCR.use_cassette("blocks/#{DEFAULT_NODE_BLOCK_NUMBER}", + record: :new_episodes) do node_data_processor.call AccountBook.where(ckb_transaction_id: block.ckb_transactions.pluck(:id)).pluck(:address_id).uniq.each do |id| assert_equal 0, $redis.zcard("Address/txs/#{id}") @@ -3446,23 +3851,23 @@ class NodeDataProcessorTest < ActiveSupport::TestCase address = create(:address) block = create(:block, :with_block_hash) ckb_transaction1 = create(:ckb_transaction, - tx_hash: "0x498315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block: block) + tx_hash: "0x498315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block:) ckb_transaction2 = create(:ckb_transaction, - tx_hash: "0x598315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block: block) + tx_hash: "0x598315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block:) lock = create(:lock_script) create(:cell_output, ckb_transaction: ckb_transaction1, cell_index: 1, tx_hash: "0x498315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", - block: block, + block:, capacity: 10**8 * 1000, - address: address, + address:, lock_script_id: lock.id) create(:cell_output, ckb_transaction: ckb_transaction2, cell_index: 2, tx_hash: "0x598315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", - block: block, + block:, capacity: 10**8 * 1000, - address: address, + address:, lock_script_id: lock.id) tx1 = node_block.transactions.first output1 = tx1.outputs.first @@ -3483,31 +3888,31 @@ class NodeDataProcessorTest < ActiveSupport::TestCase block = create(:block, :with_block_hash) ckb_transaction1 = create(:ckb_transaction, tx_hash: "0x498315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", - block: block) + block:) ckb_transaction2 = create(:ckb_transaction, tx_hash: "0x598315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", - block: block) + block:) lock = create(:lock_script) create(:cell_output, ckb_transaction: ckb_transaction1, cell_index: 1, tx_hash: "0x498315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", - block: block, + block:, capacity: 10**8 * 1000, - address: address, + address:, lock_script_id: lock.id) create(:cell_output, ckb_transaction: ckb_transaction2, cell_index: 2, tx_hash: "0x598315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", - block: block, + block:, capacity: 10**8 * 1000, - address: address, + address:, lock_script_id: lock.id) tx1 = node_block.transactions.first output1 = tx1.outputs.first output1.type = CKB::Types::Script.new( args: "0xb2e61ff569acf041b3c2c17724e2379c581eeac3", hash_type: "type", - code_hash: Settings.dao_type_hash + code_hash: Settings.dao_type_hash, ) output1.capacity = 10**8 * 1000 tx1.outputs << output1 @@ -3519,12 +3924,13 @@ class NodeDataProcessorTest < ActiveSupport::TestCase factory_cell_script = CKB::Types::Script.new( code_hash: old_factory_cell.code_hash, hash_type: "type", - args: old_factory_cell.args + args: old_factory_cell.args, ) type_script1 = create(:type_script, args: factory_cell_script.args, code_hash: factory_cell_script.code_hash, hash_type: "type") - block1 = create(:block, :with_block_hash, number: DEFAULT_NODE_BLOCK_NUMBER - 1) + block1 = create(:block, :with_block_hash, + number: DEFAULT_NODE_BLOCK_NUMBER - 1) tx1 = create(:ckb_transaction, block: block1) input_address1 = create(:address) address1_lock = create(:lock_script, address_id: input_address1.id, @@ -3543,7 +3949,7 @@ class NodeDataProcessorTest < ActiveSupport::TestCase lock1 = CKB::Types::Script.new( code_hash: Settings.secp_cell_type_hash, hash_type: "type", - args: address1_lock.args + args: address1_lock.args, ) header = CKB::Types::BlockHeader.new( @@ -3558,36 +3964,40 @@ class NodeDataProcessorTest < ActiveSupport::TestCase extra_hash: "0x#{SecureRandom.hex(32)}", version: 0, epoch: 1, - dao: "0x01000000000000000000c16ff286230000a3a65e97fd03000057c138586f0000" + dao: "0x01000000000000000000c16ff286230000a3a65e97fd03000057c138586f0000", ) inputs = [ - CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new(tx_hash: tx1.tx_hash, index: 0)) + CKB::Types::Input.new(previous_output: CKB::Types::OutPoint.new( + tx_hash: tx1.tx_hash, index: 0, + )), ] outputs = [ - CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock1, type: factory_cell_script) + CKB::Types::Output.new(capacity: 40000 * 10**8, lock: lock1, + type: factory_cell_script), ] miner_lock = CKB::Types::Script.new( code_hash: Settings.secp_cell_type_hash, hash_type: "type", - args: "0x#{SecureRandom.hex(20)}" + args: "0x#{SecureRandom.hex(20)}", ) cellbase_inputs = [ CKB::Types::Input.new( previous_output: CKB::Types::OutPoint.new( - tx_hash: "0x0000000000000000000000000000000000000000000000000000000000000000", index: 4294967295 + tx_hash: "0x0000000000000000000000000000000000000000000000000000000000000000", index: 4294967295, ), since: 3000 - ) + ), ] cellbase_outputs = [ - CKB::Types::Output.new(capacity: 200986682127, lock: miner_lock) + CKB::Types::Output.new(capacity: 200986682127, lock: miner_lock), ] transactions = [ CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs: cellbase_inputs, outputs: cellbase_outputs, outputs_data: %w[0x], witnesses: ["0x590000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd800000000"]), - CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs: inputs, - outputs: outputs, outputs_data: %w[0x24ff5a9ab8c38d195ce2b4ea75ca89870009522b4b205631204e310009522b4b205631204e3100156465762e6b6f6c6c6563742e6d652f746f6b656e73000000030000000100000000], witnesses: ["0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000"]) + CKB::Types::Transaction.new(hash: "0x#{SecureRandom.hex(32)}", cell_deps: [], header_deps: [], inputs:, + outputs:, outputs_data: %w[0x24ff5a9ab8c38d195ce2b4ea75ca89870009522b4b205631204e310009522b4b205631204e3100156465762e6b6f6c6c6563742e6d652f746f6b656e73000000030000000100000000], witnesses: ["0x5d0000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce801140000003954acece65096bfa81258983ddb83915fc56bd804000000123456780000000000000000"]), ] - node_block = CKB::Types::Block.new(uncles: [], proposals: [], transactions: transactions, header: header) + node_block = CKB::Types::Block.new(uncles: [], proposals: [], + transactions:, header:) block = node_data_processor.process_block(node_block) assert_equal "R+K V1 N1", old_factory_cell.reload.symbol end @@ -3597,31 +4007,37 @@ class NodeDataProcessorTest < ActiveSupport::TestCase CkbSync::Api.any_instance.stubs(:omiga_inscription_info_code_hash).returns("0x50fdea2d0030a8d0b3d69f883b471cab2a29cae6f01923f19cecac0f27fdaaa6") VCR.use_cassette("blocks/31") do node_block = CkbSync::Api.instance.get_block_by_number(31) - block1 = create(:block, :with_block_hash, number: node_block.header.number - 1) - tx1 = create(:ckb_transaction, block: block1, tx_hash: "0x3e89753ebca825e1504498eb18b56576d5b7eff59fe033346a10ab9e8ca359a4") + block1 = create(:block, :with_block_hash, + number: node_block.header.number - 1) + tx1 = create(:ckb_transaction, block: block1, + tx_hash: "0x3e89753ebca825e1504498eb18b56576d5b7eff59fe033346a10ab9e8ca359a4") input_address1 = create(:address) address1_lock = create(:lock_script, address_id: input_address1.id, - args: "0x#{SecureRandom.hex(20)}", - code_hash: Settings.secp_cell_type_hash, - hash_type: "type") + args: "0x#{SecureRandom.hex(20)}", + code_hash: Settings.secp_cell_type_hash, + hash_type: "type") output1 = create(:cell_output, ckb_transaction: tx1, - block: block1, capacity: 50000000 * 10**8, - tx_hash: tx1.tx_hash, - cell_index: 1, - address: input_address1, - cell_type: "normal", - lock_script_id: address1_lock.id, - type_script_id: nil) + block: block1, capacity: 50000000 * 10**8, + tx_hash: tx1.tx_hash, + cell_index: 1, + address: input_address1, + cell_type: "normal", + lock_script_id: address1_lock.id, + type_script_id: nil) node_data_processor.process_block(node_block) - assert_equal CellOutput.find_by(tx_hash: "0xb865e4d50a72f08acf45389fcd1f76eefe6eb3377733ffc3c1b934a57a86b5dc", cell_index: 0).cell_type, "omiga_inscription_info" + assert_equal CellOutput.find_by(tx_hash: "0xb865e4d50a72f08acf45389fcd1f76eefe6eb3377733ffc3c1b934a57a86b5dc", cell_index: 0).cell_type, + "omiga_inscription_info" info = OmigaInscriptionInfo.first - assert_equal info.code_hash, "0x50fdea2d0030a8d0b3d69f883b471cab2a29cae6f01923f19cecac0f27fdaaa6" + assert_equal info.code_hash, + "0x50fdea2d0030a8d0b3d69f883b471cab2a29cae6f01923f19cecac0f27fdaaa6" assert_equal info.hash_type, "type" - assert_equal info.args, "0xcd89d8f36593a9a82501c024c5cdc4877ca11c5b3d5831b3e78334aecb978f0d" + assert_equal info.args, + "0xcd89d8f36593a9a82501c024c5cdc4877ca11c5b3d5831b3e78334aecb978f0d" assert_equal info.decimal, 0.8e1 assert_equal info.name, "CKB Fist Inscription" assert_equal info.symbol, "CKBI" - assert_equal info.udt_hash, "0x5fa66c8d5f43914f85d3083e0529931883a5b0a14282f891201069f1b5067908" + assert_equal info.udt_hash, + "0x5fa66c8d5f43914f85d3083e0529931883a5b0a14282f891201069f1b5067908" assert_equal info.expected_supply, 0.21e16 assert_equal info.mint_limit, 0.1e12 assert_equal info.mint_status, "minting" @@ -3635,40 +4051,45 @@ class NodeDataProcessorTest < ActiveSupport::TestCase VCR.use_cassette("blocks/32") do node_block = CkbSync::Api.instance.get_block_by_number(32) - block1 = create(:block, :with_block_hash, number: node_block.header.number - 1) - tx1 = create(:ckb_transaction, block: block1, tx_hash: "0x3e89753ebca825e1504498eb18b56576d5b7eff59fe033346a10ab9e8ca359a4") + block1 = create(:block, :with_block_hash, + number: node_block.header.number - 1) + tx1 = create(:ckb_transaction, block: block1, + tx_hash: "0x3e89753ebca825e1504498eb18b56576d5b7eff59fe033346a10ab9e8ca359a4") input_address1 = create(:address) address1_lock = create(:lock_script, address_id: input_address1.id, - args: "0x#{SecureRandom.hex(20)}", - code_hash: Settings.secp_cell_type_hash, - hash_type: "type") + args: "0x#{SecureRandom.hex(20)}", + code_hash: Settings.secp_cell_type_hash, + hash_type: "type") output1 = create(:cell_output, ckb_transaction: tx1, - block: block1, capacity: 50000000 * 10**8, - tx_hash: tx1.tx_hash, - cell_index: 1, - address: input_address1, - cell_type: "normal", - lock_script_id: address1_lock.id, - type_script_id: nil) - create(:omiga_inscription_info, - code_hash: "0x50fdea2d0030a8d0b3d69f883b471cab2a29cae6f01923f19cecac0f27fdaaa6", - hash_type: "type", - args: "0xcd89d8f36593a9a82501c024c5cdc4877ca11c5b3d5831b3e78334aecb978f0d", - decimal: 0.8e1, - name: "CKB Fist Inscription", - symbol: "CKBI", - udt_hash: "0x5fa66c8d5f43914f85d3083e0529931883a5b0a14282f891201069f1b5067908", - expected_supply: 0.21e16, - mint_limit: 0.1e12, - mint_status: "minting", - udt_id: nil - ) + block: block1, capacity: 50000000 * 10**8, + tx_hash: tx1.tx_hash, + cell_index: 1, + address: input_address1, + cell_type: "normal", + lock_script_id: address1_lock.id, + type_script_id: nil) + info = create(:omiga_inscription_info, + code_hash: "0x50fdea2d0030a8d0b3d69f883b471cab2a29cae6f01923f19cecac0f27fdaaa6", + hash_type: "type", + args: "0xcd89d8f36593a9a82501c024c5cdc4877ca11c5b3d5831b3e78334aecb978f0d", + decimal: 0.8e1, + name: "CKB Fist Inscription", + symbol: "CKBI", + udt_hash: "0x5fa66c8d5f43914f85d3083e0529931883a5b0a14282f891201069f1b5067908", + expected_supply: 0.21e16, + mint_limit: 0.1e12, + mint_status: "minting", + udt_id: nil) node_data_processor.process_block(node_block) + assert_equal CellOutput.find_by(type_hash: info.udt_hash).udt_amount, + 0.1e12 assert_equal 1, UdtAccount.count + assert_equal 0.1e12, UdtAccount.first.amount assert_equal 1, UdtTransaction.count omiga_inscription = Udt.first assert_equal OmigaInscriptionInfo.first.udt_id, omiga_inscription.id - assert_equal omiga_inscription.type_hash, "0x5fa66c8d5f43914f85d3083e0529931883a5b0a14282f891201069f1b5067908" + assert_equal omiga_inscription.type_hash, + "0x5fa66c8d5f43914f85d3083e0529931883a5b0a14282f891201069f1b5067908" end end @@ -3681,16 +4102,16 @@ def node_data_processor def fake_dao_withdraw_transaction(node_block) block = create(:block, :with_block_hash, timestamp: 1557382351075) ckb_transaction1 = create(:ckb_transaction, - tx_hash: "0x498315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block: block) + tx_hash: "0x498315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block:) ckb_transaction2 = create(:ckb_transaction, - tx_hash: "0x598315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block: block) + tx_hash: "0x598315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block:) lock = create(:lock_script) cell_output1 = create(:cell_output, ckb_transaction: ckb_transaction1, cell_index: 1, - tx_hash: "0x498315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block: block, cell_type: "nervos_dao_withdrawing", capacity: 10**8 * 1000, data: CKB::Utils.bin_to_hex("\x02" * 8), lock_script_id: lock.id) + tx_hash: "0x498315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block:, cell_type: "nervos_dao_withdrawing", capacity: 10**8 * 1000, data: CKB::Utils.bin_to_hex("\x02" * 8), lock_script_id: lock.id) cell_output2 = create(:cell_output, ckb_transaction: ckb_transaction2, cell_index: 1, - tx_hash: "0x398315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e2", block: block, consumed_by: ckb_transaction2, cell_type: "nervos_dao_deposit", capacity: 10**8 * 1000, data: CKB::Utils.bin_to_hex("\x00" * 8), lock_script_id: lock.id) + tx_hash: "0x398315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e2", block:, consumed_by: ckb_transaction2, cell_type: "nervos_dao_deposit", capacity: 10**8 * 1000, data: CKB::Utils.bin_to_hex("\x00" * 8), lock_script_id: lock.id) cell_output3 = create(:cell_output, ckb_transaction: ckb_transaction2, cell_index: 2, - tx_hash: "0x598315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block: block, lock_script_id: lock.id) + tx_hash: "0x598315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block:, lock_script_id: lock.id) cell_output1.address.update(balance: 10**8 * 1000) cell_output2.address.update(balance: 10**8 * 1000) cell_output3.address.update(balance: 10**8 * 1000) @@ -3716,13 +4137,13 @@ def fake_dao_deposit_transaction(node_block) block = create(:block, :with_block_hash, timestamp: 1557382351075) lock = create(:lock_script) ckb_transaction1 = create(:ckb_transaction, - tx_hash: "0x498315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block: block) + tx_hash: "0x498315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block:) ckb_transaction2 = create(:ckb_transaction, - tx_hash: "0x598315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block: block) + tx_hash: "0x598315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block:) cell_output1 = create(:cell_output, ckb_transaction: ckb_transaction1, cell_index: 1, - tx_hash: "0x498315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block: block, capacity: 10**8 * 1000, lock_script_id: lock.id) + tx_hash: "0x498315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block:, capacity: 10**8 * 1000, lock_script_id: lock.id) cell_output2 = create(:cell_output, ckb_transaction: ckb_transaction2, cell_index: 2, - tx_hash: "0x598315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block: block, capacity: 10**8 * 1000, lock_script_id: lock.id) + tx_hash: "0x598315db9c7ba144cca74d2e9122ac9b3a3da1641b2975ae321d91ec34f1c0e3", block:, capacity: 10**8 * 1000, lock_script_id: lock.id) cell_output1.address.update(balance: 10**8 * 1000) cell_output2.address.update(balance: 10**8 * 1000) tx = node_block.transactions.first diff --git a/test/utils/ckb_utils_test.rb b/test/utils/ckb_utils_test.rb index 5a8168ea6..d0c56573d 100644 --- a/test/utils/ckb_utils_test.rb +++ b/test/utils/ckb_utils_test.rb @@ -467,6 +467,12 @@ class CkbUtilsTest < ActiveSupport::TestCase assert_equal info[:name], nil end + test "parse omiga inscrpition data" do + data = "0x00e87648170000000000000000000000" + info = CkbUtils.parse_omiga_inscription_data(data) + assert_equal info[:mint_limit], 100000000000 + end + private def node_data_processor From e789ecc8591ab7046ab854899924ce96c262bf00 Mon Sep 17 00:00:00 2001 From: Miles Zhang Date: Wed, 10 Jan 2024 10:39:30 +0800 Subject: [PATCH 4/8] feat: remove udt name and symbol validation (#1562) Signed-off-by: Miles Zhang --- app/models/udt.rb | 2 -- app/models/udt_account.rb | 2 -- test/models/udt_account_test.rb | 2 -- test/models/udt_test.rb | 22 ++++++++++------------ 4 files changed, 10 insertions(+), 18 deletions(-) diff --git a/app/models/udt.rb b/app/models/udt.rb index 1064902c1..54ec7214d 100644 --- a/app/models/udt.rb +++ b/app/models/udt.rb @@ -9,8 +9,6 @@ class Udt < ApplicationRecord omiga_inscription: 4 } validates_presence_of :total_amount - validates_length_of :symbol, minimum: 1, maximum: 16, allow_nil: true - validates_length_of :full_name, minimum: 1, maximum: 100, allow_nil: true validates :decimal, numericality: { greater_than_or_equal_to: 0, less_than_or_equal_to: 39 }, allow_nil: true validates :total_amount, numericality: { greater_than_or_equal_to: 0 } diff --git a/app/models/udt_account.rb b/app/models/udt_account.rb index e61976b03..568cf9da3 100644 --- a/app/models/udt_account.rb +++ b/app/models/udt_account.rb @@ -6,8 +6,6 @@ class UdtAccount < ApplicationRecord belongs_to :udt validates_presence_of :amount - validates_length_of :symbol, minimum: 1, maximum: 16, allow_nil: true - validates_length_of :full_name, minimum: 1, maximum: 100, allow_nil: true validates :decimal, numericality: { greater_than_or_equal_to: 0, less_than_or_equal_to: 39 }, allow_nil: true validates :amount, numericality: { greater_than_or_equal_to: 0 } diff --git a/test/models/udt_account_test.rb b/test/models/udt_account_test.rb index 87b4967cd..215941ee0 100644 --- a/test/models/udt_account_test.rb +++ b/test/models/udt_account_test.rb @@ -9,7 +9,5 @@ class UdtAccountTest < ActiveSupport::TestCase should validate_presence_of(:amount) should validate_numericality_of(:decimal).allow_nil.is_greater_than_or_equal_to(0).is_less_than_or_equal_to(39) should validate_numericality_of(:amount).is_greater_than_or_equal_to(0) - should validate_length_of(:symbol).allow_nil.is_at_least(1).is_at_most(16) - should validate_length_of(:full_name).allow_nil.is_at_least(1).is_at_most(100) end end diff --git a/test/models/udt_test.rb b/test/models/udt_test.rb index d2188f694..1a20c1447 100644 --- a/test/models/udt_test.rb +++ b/test/models/udt_test.rb @@ -5,8 +5,6 @@ class UdtTest < ActiveSupport::TestCase should validate_presence_of(:total_amount) should validate_numericality_of(:decimal).allow_nil.is_greater_than_or_equal_to(0).is_less_than_or_equal_to(39) should validate_numericality_of(:total_amount).is_greater_than_or_equal_to(0) - should validate_length_of(:symbol).allow_nil.is_at_least(1).is_at_most(16) - should validate_length_of(:full_name).allow_nil.is_at_least(1).is_at_most(100) end test "should return node type script when the udt is published" do @@ -14,7 +12,7 @@ class UdtTest < ActiveSupport::TestCase node_type_script = { args: udt.args, code_hash: udt.code_hash, - hash_type: udt.hash_type + hash_type: udt.hash_type, } assert_equal node_type_script, udt.type_script @@ -32,19 +30,19 @@ class UdtTest < ActiveSupport::TestCase 30.times do |number| block = create(:block, :with_block_hash) if number % 2 == 0 - tx = create(:ckb_transaction, block: block, tags: ["udt"], contained_udt_ids: [udt.id], + tx = create(:ckb_transaction, block:, tags: ["udt"], contained_udt_ids: [udt.id], contained_address_ids: [address.id]) - create(:cell_output, block: block, ckb_transaction: tx, cell_type: "udt", type_hash: udt.type_hash, - address: address) + create(:cell_output, block:, ckb_transaction: tx, cell_type: "udt", type_hash: udt.type_hash, + address:) else - tx = create(:ckb_transaction, block: block, tags: ["udt"], contained_udt_ids: [udt.id], + tx = create(:ckb_transaction, block:, tags: ["udt"], contained_udt_ids: [udt.id], contained_address_ids: [address.id]) - tx1 = create(:ckb_transaction, block: block, tags: ["udt"], contained_udt_ids: [udt.id], + tx1 = create(:ckb_transaction, block:, tags: ["udt"], contained_udt_ids: [udt.id], contained_address_ids: [address.id]) - create(:cell_output, block: block, ckb_transaction: tx1, cell_type: "udt", type_hash: udt.type_hash, - address: address) - create(:cell_output, block: block, ckb_transaction: tx, cell_type: "udt", type_hash: udt.type_hash, - consumed_by_id: tx1, address: address) + create(:cell_output, block:, ckb_transaction: tx1, cell_type: "udt", type_hash: udt.type_hash, + address:) + create(:cell_output, block:, ckb_transaction: tx, cell_type: "udt", type_hash: udt.type_hash, + consumed_by_id: tx1, address:) end end From c797ff1ed7b01cb27027cec079c7c8bef86dfdb1 Mon Sep 17 00:00:00 2001 From: Miles Zhang Date: Thu, 11 Jan 2024 15:17:06 +0800 Subject: [PATCH 5/8] Udt account of omiga inscription api (#1563) * chore: add xudt mainnet code hash configuration Signed-off-by: Miles Zhang * feat: return omiga inscription udt account for address api Signed-off-by: Miles Zhang * feat: update omiga inscription task Signed-off-by: Miles Zhang --------- Signed-off-by: Miles Zhang --- app/serializers/address_serializer.rb | 42 +++++--- config/settings.mainnet.yml | 2 +- .../update_omiga_inscription_udt.rake | 86 ++++++++++++++++ .../api/v1/addresses_controller_test.rb | 97 +++++++++++++------ test/factories/udt.rb | 3 - .../update_omiga_inscription_udt_test.rb | 76 +++++++++++++++ 6 files changed, 260 insertions(+), 46 deletions(-) create mode 100644 lib/tasks/migration/update_omiga_inscription_udt.rake create mode 100644 test/tasks/migrations/update_omiga_inscription_udt_test.rb diff --git a/app/serializers/address_serializer.rb b/app/serializers/address_serializer.rb index bd5155e03..f42bcec68 100644 --- a/app/serializers/address_serializer.rb +++ b/app/serializers/address_serializer.rb @@ -21,7 +21,9 @@ class AddressSerializer attribute :is_special do |object| object.special?.to_s end - attribute :special_address, if: Proc.new { |record| record.special? } do |object| + attribute :special_address, if: Proc.new { |record| + record.special? + } do |object| Settings.special_addresses[object.address_hash] end attribute :live_cells_count do |object| @@ -45,7 +47,19 @@ class AddressSerializer udt_icon_file: udt_account.udt_icon_file, udt_type: udt_account.udt_type, display_name: udt_account.display_name, - uan: udt_account.uan + uan: udt_account.uan, + } + elsif udt_account.udt_type == "omiga_inscription" + info = udt_account.udt.omiga_inscription_info + { + symbol: udt_account.symbol, + decimal: udt_account.decimal.to_s, + amount: udt_account.amount.to_s, + type_hash: udt_account.type_hash, + udt_type: udt_account.udt_type, + udt_amount: udt_account.udt.total_amount.to_s, + expected_supply: info.expected_supply.to_s, + mint_status: info.mint_status, } elsif udt_account.udt_type == "m_nft_token" ts = TypeScript.find_by script_hash: udt_account.type_hash @@ -59,20 +73,20 @@ class AddressSerializer amount: udt_account.amount.to_s, type_hash: udt_account.type_hash, collection: { - type_hash: coll&.type_script&.script_hash + type_hash: coll&.type_script&.script_hash, }, udt_icon_file: udt_account.udt_icon_file, - udt_type: udt_account.udt_type + udt_type: udt_account.udt_type, } elsif udt_account.udt_type == "nrc_721_token" udt = udt_account.udt Sentry.capture_message("Missing nrc_factory_cell", extra: { - address: object.address_hash, - udt: udt.symbol, - full_name: udt.full_name, - code_hash: udt.code_hash, - args: udt.args - }) + address: object.address_hash, + udt: udt.symbol, + full_name: udt.full_name, + code_hash: udt.code_hash, + args: udt.args, + }) factory_cell = udt_account.udt.nrc_factory_cell coll = factory_cell&.token_collection { @@ -80,10 +94,10 @@ class AddressSerializer amount: udt_account.nft_token_id.to_s, type_hash: udt_account.type_hash, collection: { - type_hash: coll&.type_script&.script_hash + type_hash: coll&.type_script&.script_hash, }, udt_icon_file: "#{udt_account.udt.nrc_factory_cell&.base_token_uri}/#{udt_account.nft_token_id}", - udt_type: udt_account.udt_type + udt_type: udt_account.udt_type, } elsif udt_account.udt_type == "spore_cell" ts = TypeScript.where(script_hash: udt_account.type_hash).first @@ -97,10 +111,10 @@ class AddressSerializer amount: udt_account.nft_token_id.to_s, type_hash: udt_account.type_hash, collection: { - type_hash: coll&.type_script&.script_hash + type_hash: coll&.type_script&.script_hash, }, udt_icon_file: data, - udt_type: udt_account.udt_type + udt_type: udt_account.udt_type, } end end diff --git a/config/settings.mainnet.yml b/config/settings.mainnet.yml index 7662437c7..e1cef37d6 100644 --- a/config/settings.mainnet.yml +++ b/config/settings.mainnet.yml @@ -29,7 +29,7 @@ omiga_inscription_info_code_hash: "" omiga_inscription_code_hash: "" # xudt -xudt_code_hash: "" +xudt_code_hash: "0x50bd8d6680b8b9cf98b73f3c08faf8b2a21914311954118ad6609be6e78a1b95" # hash length of an attribute(especially which comes from bytea column), # e.g. Block.uncle_block_hashes: "0x587f354162afd133b4a4f7a4b621d11e043c3c08b0af2801f1686b5403b14953", which has a length of 66 ( 2 + 64) diff --git a/lib/tasks/migration/update_omiga_inscription_udt.rake b/lib/tasks/migration/update_omiga_inscription_udt.rake new file mode 100644 index 000000000..2aa452a0f --- /dev/null +++ b/lib/tasks/migration/update_omiga_inscription_udt.rake @@ -0,0 +1,86 @@ +namespace :migration do + desc "Usage: RAILS_ENV=production bundle exec rake migration:update_omiga_inscription_udt" + task update_omiga_inscription_udt: :environment do + info_ts_ids = TypeScript.where(code_hash: CkbSync::Api.instance.omiga_inscription_info_code_hash).pluck(:id) + info_outputs = CellOutput.where(type_script_id: info_ts_ids) + info_outputs.update_all(cell_type: "omiga_inscription_info") + + info_outputs.each do |output| + info = CkbUtils.parse_omiga_inscription_info(output.data) + # ignore old version data + if output.data.slice(-2..-1).in?(["00", "01", "02"]) + OmigaInscriptionInfo.upsert(info.merge(output.type_script.to_node), + unique_by: :udt_hash) + end + end + + xudt_ts_ids = TypeScript.where(code_hash: CkbSync::Api.instance.xudt_code_hash).pluck(:id) + xudt_ts_ids.each do |tid| + xudt_outputs = CellOutput.where(type_script_id: tid) + xudt_outputs.each do |output| + if OmigaInscriptionInfo.where(udt_hash: output.type_hash).exists? + info = OmigaInscriptionInfo.find_by!(udt_hash: output.type_hash) + output.update(cell_type: "omiga_inscription", + udt_amount: info.mint_limit) + if info.udt_id.nil? + nft_token_attr = {} + nft_token_attr[:full_name] = info.name.presence + nft_token_attr[:symbol] = info.symbol.presence + nft_token_attr[:decimal] = info.decimal + nft_token_attr[:published] = true + udt = Udt.create_or_find_by!({ + type_hash: output.type_hash, + udt_type: "omiga_inscription", + block_timestamp: output.block.timestamp, + args: output.type_script.args, + code_hash: output.type_script.code_hash, + hash_type: output.type_script.hash_type, + }.merge(nft_token_attr)) + info.update!(udt_id: udt.id) + end + else + output.update(cell_type: "xudt") + end + end + end + + # udt_transaction + Udt.where(udt_type: "omiga_inscription").each do |udt| + outputs = CellOutput.omiga_inscription.where(type_hash: udt.type_hash).select( + :address_id, :ckb_transaction_id + ).distinct + udt_transaction_attrs = + outputs.map do |output| + { udt_id: udt.id, ckb_transaction_id: output.ckb_transaction_id } + end + UdtTransaction.insert_all(udt_transaction_attrs) + + address_udt_transaction_attrs = + outputs.map do |output| + { address_id: output.address_id, + ckb_transaction_id: output.ckb_transaction_id } + end + AddressUdtTransaction.insert_all(address_udt_transaction_attrs) + end + + # udt_account + Udt.where(udt_type: "omiga_inscription").each do |udt| + # {address_id => udt_amount} + results = CellOutput.live.omiga_inscription.where(type_hash: udt.type_hash).select(:address_id).group(:address_id).sum(:udt_amount) + attrs = + results.map do |address_id, udt_amount| + { + address_id:, udt_type: udt.udt_type, full_name: udt.full_name, symbol: udt.symbol, decimal: udt.decimal, + published: udt.published, code_hash: udt.code_hash, type_hash: udt.type_hash, amount: udt_amount, udt_id: udt.id + } + end + + unless attrs.empty? + UdtAccount.insert_all(attrs) + udt.update(total_amount: results.sum { |_k, v| v }) + end + end + + puts "done" + end +end diff --git a/test/controllers/api/v1/addresses_controller_test.rb b/test/controllers/api/v1/addresses_controller_test.rb index 41b1b321e..f8e2ff670 100644 --- a/test/controllers/api/v1/addresses_controller_test.rb +++ b/test/controllers/api/v1/addresses_controller_test.rb @@ -22,7 +22,8 @@ class AddressesControllerTest < ActionDispatch::IntegrationTest test "should respond with 415 Unsupported Media Type when Content-Type is wrong" do address = create(:address, :with_lock_script) - get api_v1_address_url(address.address_hash), headers: { "Content-Type": "text/plain" } + get api_v1_address_url(address.address_hash), + headers: { "Content-Type": "text/plain" } assert_equal 415, response.status end @@ -30,9 +31,11 @@ class AddressesControllerTest < ActionDispatch::IntegrationTest test "should respond with error object when Content-Type is wrong" do address = create(:address, :with_lock_script) error_object = Api::V1::Exceptions::InvalidContentTypeError.new - response_json = RequestErrorSerializer.new([error_object], message: error_object.title).serialized_json + response_json = RequestErrorSerializer.new([error_object], + message: error_object.title).serialized_json - get api_v1_address_url(address.address_hash), headers: { "Content-Type": "text/plain" } + get api_v1_address_url(address.address_hash), + headers: { "Content-Type": "text/plain" } assert_equal response_json, response.body end @@ -41,7 +44,8 @@ class AddressesControllerTest < ActionDispatch::IntegrationTest address = create(:address, :with_lock_script) get api_v1_address_url(address.address_hash), - headers: { "Content-Type": "application/vnd.api+json", "Accept": "application/json" } + headers: { "Content-Type": "application/vnd.api+json", + "Accept": "application/json" } assert_equal 406, response.status end @@ -49,17 +53,20 @@ class AddressesControllerTest < ActionDispatch::IntegrationTest test "should respond with error object when Accept is wrong" do address = create(:address, :with_lock_script) error_object = Api::V1::Exceptions::InvalidAcceptError.new - response_json = RequestErrorSerializer.new([error_object], message: error_object.title).serialized_json + response_json = RequestErrorSerializer.new([error_object], + message: error_object.title).serialized_json get api_v1_address_url(address.address_hash), - headers: { "Content-Type": "application/vnd.api+json", "Accept": "application/json" } + headers: { "Content-Type": "application/vnd.api+json", + "Accept": "application/json" } assert_equal response_json, response.body end test "should return error object when id is not a address hash" do error_object = Api::V1::Exceptions::AddressHashInvalidError.new - response_json = RequestErrorSerializer.new([error_object], message: error_object.title).serialized_json + response_json = RequestErrorSerializer.new([error_object], + message: error_object.title).serialized_json valid_get api_v1_address_url("9034fwefwef") @@ -72,7 +79,8 @@ class AddressesControllerTest < ActionDispatch::IntegrationTest valid_get api_v1_address_url(address.address_hash) - assert_equal AddressSerializer.new(address).serialized_json, response.body + assert_equal AddressSerializer.new(address).serialized_json, + response.body end test "should return corresponding data with given lock hash" do @@ -80,7 +88,8 @@ class AddressesControllerTest < ActionDispatch::IntegrationTest valid_get api_v1_address_url(address.lock_hash) - assert_equal LockHashSerializer.new(address).serialized_json, response.body + assert_equal LockHashSerializer.new(address).serialized_json, + response.body end test "should contain right keys in the serialized object when call show" do @@ -104,26 +113,31 @@ class AddressesControllerTest < ActionDispatch::IntegrationTest end test "should return special address when query address is special" do - address = create(:address, :with_lock_script, address_hash: "ckb1qyq0hcfpff4h8w8zvy44uurvlgdrr09tefwqx266dl") + address = create(:address, :with_lock_script, + address_hash: "ckb1qyq0hcfpff4h8w8zvy44uurvlgdrr09tefwqx266dl") valid_get api_v1_address_url(address.address_hash) - assert_equal Settings.special_addresses[address.address_hash], json.dig("data", "attributes", "special_address") + assert_equal Settings.special_addresses[address.address_hash], + json.dig("data", "attributes", "special_address") end test "should not return special address when query address is not special" do - address = create(:address, :with_lock_script, address_hash: "ckb1qyqdmeuqrsrnm7e5vnrmruzmsp4m9wacf6vsxasryq") + address = create(:address, :with_lock_script, + address_hash: "ckb1qyqdmeuqrsrnm7e5vnrmruzmsp4m9wacf6vsxasryq") valid_get api_v1_address_url(address.address_hash) assert_nil json.dig("data", "attributes", "special_address") end test "should support full address query when short address's lock script exists" do - address = create(:address, :with_lock_script, address_hash: "ckb1qyqt8xaupvm8837nv3gtc9x0ekkj64vud3jqfwyw5v") + address = create(:address, :with_lock_script, + address_hash: "ckb1qyqt8xaupvm8837nv3gtc9x0ekkj64vud3jqfwyw5v") query_key = "ckb1qjda0cr08m85hc8jlnfp3zer7xulejywt49kt2rr0vthywaa50xw3vumhs9nvu786dj9p0q5elx66t24n3kxgj53qks" address.query_address = query_key valid_get api_v1_address_url(query_key) - assert_equal AddressSerializer.new(address).serialized_json, response.body + assert_equal AddressSerializer.new(address).serialized_json, + response.body end test "should support short address query when full address's lock script exists" do @@ -133,12 +147,13 @@ class AddressesControllerTest < ActionDispatch::IntegrationTest address.query_address = query_key valid_get api_v1_address_url(query_key) - assert_equal AddressSerializer.new(address).serialized_json, response.body + assert_equal AddressSerializer.new(address).serialized_json, + response.body end test "should return published udt accounts with given address hash" do address = create(:address, :with_lock_script) - udt_account = create(:udt_account, published: true, address: address) + udt_account = create(:udt_account, published: true, address:) address.query_address = address.address_hash valid_get api_v1_address_url(address.address_hash) @@ -151,14 +166,14 @@ class AddressesControllerTest < ActionDispatch::IntegrationTest "udt_icon_file" => udt_account.udt_icon_file, "udt_type" => udt_account.udt_type, "display_name" => nil, - "uan" => nil - } + "uan" => nil, + }, ], json.dig("data", "attributes", "udt_accounts") end test "should not return unpublished udt accounts with given address hash" do address = create(:address, :with_lock_script) - create(:udt_account, address: address) + create(:udt_account, address:) address.query_address = address.address_hash valid_get api_v1_address_url(address.address_hash) @@ -167,7 +182,8 @@ class AddressesControllerTest < ActionDispatch::IntegrationTest end test "should return balance occupied" do - address = create(:address, :with_lock_script, address_hash: "ckb1qyq0hcfpff4h8w8zvy44uurvlgdrr09tefwqx266dl") + address = create(:address, :with_lock_script, + address_hash: "ckb1qyq0hcfpff4h8w8zvy44uurvlgdrr09tefwqx266dl") valid_get api_v1_address_url(address.address_hash) assert_equal "0", json.dig("data", "attributes", "balance_occupied") @@ -186,7 +202,7 @@ class AddressesControllerTest < ActionDispatch::IntegrationTest args: type_script.args) udt = create(:udt, udt_type: "nrc_721_token", nrc_factory_cell_id: factory_cell.id, full_name: "OldName", symbol: "ON") - udt_account = create(:udt_account, published: true, address: address, udt_id: udt.id, nft_token_id: "1a2b3c", + udt_account = create(:udt_account, published: true, address:, udt_id: udt.id, nft_token_id: "1a2b3c", udt_type: "nrc_721_token") address.query_address = address.address_hash valid_get api_v1_address_url(address.address_hash) @@ -198,20 +214,22 @@ class AddressesControllerTest < ActionDispatch::IntegrationTest "type_hash" => nil, "udt_icon_file" => "https://dev.nrc.com/1a2b3c", "udt_type" => udt_account.udt_type, - "collection" => { "type_hash" => type_script.script_hash } - } + "collection" => { "type_hash" => type_script.script_hash }, + }, ], json.dig("data", "attributes", "udt_accounts") end test "should return spore cell udt accounts with given address hash" do - output = create :cell_output, :with_full_transaction, cell_type: "spore_cell" + output = create :cell_output, :with_full_transaction, + cell_type: "spore_cell" cell_data = create :cell_datum, cell_output: output cluster_type = create :type_script - tc = create :token_collection, type_script: cluster_type, standard: "spore" + tc = create :token_collection, type_script: cluster_type, + standard: "spore" create :token_item, collection_id: tc.id, cell_id: output.id address = create(:address, :with_lock_script) udt = create(:udt, udt_type: "spore_cell", full_name: "SporeTest") - udt_account = create(:udt_account, full_name: udt.full_name, published: true, address: address, udt_id: udt.id, nft_token_id: "123456", + udt_account = create(:udt_account, full_name: udt.full_name, published: true, address:, udt_id: udt.id, nft_token_id: "123456", udt_type: "spore_cell", type_hash: output.type_script.script_hash) address.query_address = address.address_hash valid_get api_v1_address_url(address.address_hash) @@ -222,8 +240,31 @@ class AddressesControllerTest < ActionDispatch::IntegrationTest "type_hash" => output.type_script.script_hash, "udt_icon_file" => cell_data.hex_data, "udt_type" => udt_account.udt_type, - "collection" => { "type_hash" => cluster_type.script_hash } - } + "collection" => { "type_hash" => cluster_type.script_hash }, + }, + ], json.dig("data", "attributes", "udt_accounts") + end + + test "should return omiga inscription udt accounts with given address hash" do + udt = create(:udt, :omiga_inscription, full_name: "CKB Fist Inscription", + symbol: "CKBI", decimal: 8) + info = udt.omiga_inscription_info + address = create(:address, :with_lock_script) + udt_account = create(:udt_account, symbol: udt.symbol, full_name: udt.full_name, decimal: udt.decimal, published: true, address:, udt_id: udt.id, + udt_type: "omiga_inscription", type_hash: udt.type_hash, amount: info.mint_limit) + address.query_address = address.address_hash + valid_get api_v1_address_url(address.address_hash) + assert_equal [ + { + "symbol" => udt.symbol, + "decimal" => udt.decimal.to_s, + "amount" => udt_account.amount.to_s, + "type_hash" => udt.type_hash, + "udt_type" => udt_account.udt_type, + "udt_amount" => udt_account.udt.total_amount.to_s, + "expected_supply" => info.expected_supply.to_s, + "mint_status" => info.mint_status, + }, ], json.dig("data", "attributes", "udt_accounts") end end diff --git a/test/factories/udt.rb b/test/factories/udt.rb index 8b9fd26da..bd8eb033c 100644 --- a/test/factories/udt.rb +++ b/test/factories/udt.rb @@ -38,9 +38,6 @@ trait :omiga_inscription do udt_type { "omiga_inscription" } - decimal { 0.8e1 } - full_name { "CKB Fist Inscription" } - symbol { "CKBI" } published { true } after(:create) do |udt, _evaluator| create(:omiga_inscription_info, diff --git a/test/tasks/migrations/update_omiga_inscription_udt_test.rb b/test/tasks/migrations/update_omiga_inscription_udt_test.rb new file mode 100644 index 000000000..0e2547f94 --- /dev/null +++ b/test/tasks/migrations/update_omiga_inscription_udt_test.rb @@ -0,0 +1,76 @@ +require "test_helper" +require "rake" + +class UpdateOmigaInscriptionUdtTest < ActiveSupport::TestCase + setup do + Server::Application.load_tasks if Rake::Task.tasks.empty? + end + + test "update omiga inscription" do + CkbSync::Api.any_instance.stubs(:xudt_code_hash).returns("0x25c29dc317811a6f6f3985a7a9ebc4838bd388d19d0feeecf0bcd60f6c0975bb") + CkbSync::Api.any_instance.stubs(:omiga_inscription_info_code_hash).returns("0x50fdea2d0030a8d0b3d69f883b471cab2a29cae6f01923f19cecac0f27fdaaa6") + + block1 = create(:block, :with_block_hash, number: 0) + tx1 = create(:ckb_transaction, block: block1, + tx_hash: "0x3e89753ebca825e1504498eb18b56576d5b7eff59fe033346a10ab9e8ca359a4") + input_address1 = create(:address) + address1_lock = create(:lock_script, address_id: input_address1.id) + info_ts = create(:type_script, + args: "0xcd89d8f36593a9a82501c024c5cdc4877ca11c5b3d5831b3e78334aecb978f0d", + code_hash: "0x50fdea2d0030a8d0b3d69f883b471cab2a29cae6f01923f19cecac0f27fdaaa6", + hash_type: "type") + info_output = create(:cell_output, ckb_transaction: tx1, + block: block1, capacity: 50000000 * 10**8, + tx_hash: tx1.tx_hash, + cell_index: 1, + address: input_address1, + cell_type: "normal", + lock_script_id: address1_lock.id, + type_script_id: info_ts.id) + info_output.data = "0x0814434b42204669737420496e736372697074696f6e04434b42495fa66c8d5f43914f85d3083e0529931883a5b0a14282f891201069f1b50679080040075af0750700000000000000000000e8764817000000000000000000000000" + + input_address2 = create(:address) + address2_lock = create(:lock_script, address_id: input_address2.id) + + xudt_ts = create(:type_script, + args: "0x9709d30fc21348ae1d28a197310a80aec3b8cdb5c93814d5e240f9fba85b76af", + code_hash: "0x25c29dc317811a6f6f3985a7a9ebc4838bd388d19d0feeecf0bcd60f6c0975bb", + hash_type: "type", + script_hash: "0x5fa66c8d5f43914f85d3083e0529931883a5b0a14282f891201069f1b5067908") + block2 = create(:block, :with_block_hash, number: 1) + tx2 = create(:ckb_transaction, block: block2, + tx_hash: "0xd5d38a2096c10e5d0d55def7f2b3fe58779aad831fbc9dcd594446b1f0837430") + xudt_output = create(:cell_output, ckb_transaction: tx2, + block: block2, capacity: 50000000 * 10**8, + tx_hash: tx2.tx_hash, + type_hash: xudt_ts.script_hash, + cell_index: 1, + address: input_address2, + cell_type: "normal", + lock_script_id: address2_lock.id, + type_script_id: xudt_ts.id) + input_address3 = create(:address) + address3_lock = create(:lock_script, address_id: input_address3.id) + tx3 = create(:ckb_transaction, block: block2, + tx_hash: "0xd5d38a2096c10e5d0d55def7f2b3fe58779aad831fbc9dcd594446b1f0837431") + xudt3_output = create(:cell_output, ckb_transaction: tx3, + block: block2, capacity: 50000000 * 10**8, + tx_hash: tx3.tx_hash, + type_hash: xudt_ts.script_hash, + cell_index: 1, + address: input_address3, + cell_type: "normal", + lock_script_id: address3_lock.id, + type_script_id: xudt_ts.id) + + xudt3_output.data = "0x00e87648170000000000000000000000" + Rake::Task["migration:update_omiga_inscription_udt"].execute + assert_equal 1, OmigaInscriptionInfo.count + assert_equal 1, Udt.count + assert_equal 2, UdtTransaction.count + assert_equal 2, AddressUdtTransaction.count + assert_equal 2, UdtAccount.count + assert_equal 100000000000, UdtAccount.first.amount + assert_equal 200000000000, Udt.first.total_amount + end +end From 1d4d52402b8d94bed3e2900953238dd7e7a3f0a0 Mon Sep 17 00:00:00 2001 From: Miles Zhang Date: Thu, 11 Jan 2024 18:23:22 +0800 Subject: [PATCH 6/8] fix: renaming inscription id (#1564) Signed-off-by: Miles Zhang --- app/serializers/udt_serializer.rb | 2 +- test/controllers/api/v1/omiga_inscriptions_controller_test.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/serializers/udt_serializer.rb b/app/serializers/udt_serializer.rb index a8ae703e8..a359e63d2 100644 --- a/app/serializers/udt_serializer.rb +++ b/app/serializers/udt_serializer.rb @@ -38,7 +38,7 @@ class UdtSerializer object.omiga_inscription_info.expected_supply.to_s end - attribute :inscription_id, if: Proc.new { |record, _params| + attribute :inscription_info_id, if: Proc.new { |record, _params| record.udt_type == "omiga_inscription" } do |object| object.omiga_inscription_info.args diff --git a/test/controllers/api/v1/omiga_inscriptions_controller_test.rb b/test/controllers/api/v1/omiga_inscriptions_controller_test.rb index cd8dd5654..cc6d87b0b 100644 --- a/test/controllers/api/v1/omiga_inscriptions_controller_test.rb +++ b/test/controllers/api/v1/omiga_inscriptions_controller_test.rb @@ -46,7 +46,7 @@ class OmigaInscriptionsControllerTest < ActionDispatch::IntegrationTest assert_equal %w( symbol full_name display_name uan total_amount addresses_count decimal icon_file h24_ckb_transactions_count created_at description - published type_hash type_script issuer_address mint_status mint_limit expected_supply inscription_id + published type_hash type_script issuer_address mint_status mint_limit expected_supply inscription_info_id ).sort, response_udt["attributes"].keys.sort end From eecb50fa4842505a14534a6c8fe371aae3108007 Mon Sep 17 00:00:00 2001 From: Miles Zhang Date: Mon, 15 Jan 2024 12:10:17 +0800 Subject: [PATCH 7/8] Issue 508 8 (#1566) * feat: omiga inscription sort by mint_status Signed-off-by: Miles Zhang * feat: update addresses_count for omiga_inscription task Signed-off-by: Miles Zhang * fix: update inscription total_amount in node processor Signed-off-by: Miles Zhang --------- Signed-off-by: Miles Zhang --- .../api/v1/omiga_inscriptions_controller.rb | 9 ++++++--- app/models/ckb_sync/new_node_data_processor.rb | 3 +++ .../migration/update_omiga_inscription_udt.rake | 4 +++- .../v1/omiga_inscriptions_controller_test.rb | 17 +++++++++++++++++ 4 files changed, 29 insertions(+), 4 deletions(-) diff --git a/app/controllers/api/v1/omiga_inscriptions_controller.rb b/app/controllers/api/v1/omiga_inscriptions_controller.rb index 4658be821..ee81800d9 100644 --- a/app/controllers/api/v1/omiga_inscriptions_controller.rb +++ b/app/controllers/api/v1/omiga_inscriptions_controller.rb @@ -52,15 +52,18 @@ def sort_udts(records) case sort when "created_time" then "block_timestamp" when "transactions" then "h24_ckb_transactions_count" - when "addresses_count" then "addresses_count" - else "id" + else sort end if order.nil? || !order.match?(/^(asc|desc)$/i) order = "asc" end - records.order("#{sort} #{order}") + if sort == "mint_status" + records.joins(:omiga_inscription_info).order("omiga_inscription_infos.mint_status #{order}") + else + records.order("#{sort} #{order}") + end end end end diff --git a/app/models/ckb_sync/new_node_data_processor.rb b/app/models/ckb_sync/new_node_data_processor.rb index 60edaea99..041c11153 100644 --- a/app/models/ckb_sync/new_node_data_processor.rb +++ b/app/models/ckb_sync/new_node_data_processor.rb @@ -417,6 +417,9 @@ def update_udt_info(local_block) local_block.cell_outputs.udt.select(:id, :type_hash).each do |udt_output| type_hashes << udt_output.type_hash end + local_block.cell_outputs.omiga_inscription.select(:id, :type_hash).each do |udt_output| + type_hashes << udt_output.type_hash + end local_block.ckb_transactions.pluck(:id).each do |tx_id| CellOutput.where(consumed_by_id: tx_id).udt.select(:id, :type_hash).each do |udt_output| diff --git a/lib/tasks/migration/update_omiga_inscription_udt.rake b/lib/tasks/migration/update_omiga_inscription_udt.rake index 2aa452a0f..80b4284e4 100644 --- a/lib/tasks/migration/update_omiga_inscription_udt.rake +++ b/lib/tasks/migration/update_omiga_inscription_udt.rake @@ -77,7 +77,9 @@ namespace :migration do unless attrs.empty? UdtAccount.insert_all(attrs) - udt.update(total_amount: results.sum { |_k, v| v }) + udt.update(total_amount: results.sum do |_k, v| + v + end, addresses_count: results.length) end end diff --git a/test/controllers/api/v1/omiga_inscriptions_controller_test.rb b/test/controllers/api/v1/omiga_inscriptions_controller_test.rb index cc6d87b0b..ba4d752ce 100644 --- a/test/controllers/api/v1/omiga_inscriptions_controller_test.rb +++ b/test/controllers/api/v1/omiga_inscriptions_controller_test.rb @@ -74,6 +74,23 @@ class OmigaInscriptionsControllerTest < ActionDispatch::IntegrationTest assert_equal 2, json["data"].length end + + test "should sorted by mint_status asc when sort param is mint_status" do + page = 1 + page_size = 5 + create_list(:udt, 10, :omiga_inscription) + Udt.last.omiga_inscription_info.update(mint_status: :closed) + udts = Udt.omiga_inscription.joins(:omiga_inscription_info).order("mint_status desc").page(page).per(page_size) + + valid_get api_v1_omiga_inscriptions_url, + params: { page:, page_size:, sort: "mint_status.desc" } + + options = FastJsonapi::PaginationMetaGenerator.new(request:, records: udts, page:, + page_size:).call + response_udts = UdtSerializer.new(udts, options).serialized_json + + assert_equal response_udts, response.body + end end end end From 9f94f4a1d67a31717a7ee57bff7238a491d72557 Mon Sep 17 00:00:00 2001 From: Miles Zhang Date: Mon, 15 Jan 2024 17:30:42 +0800 Subject: [PATCH 8/8] feat: return udt_type to identify which udt (#1567) Signed-off-by: Miles Zhang --- .../api/v1/udt_queries_controller.rb | 4 +- app/serializers/udt_serializer.rb | 2 +- .../v1/omiga_inscriptions_controller_test.rb | 2 +- .../api/v1/udt_queries_controller_test.rb | 30 ++-- .../api/v1/udts_controller_test.rb | 144 +++++++++++------- 5 files changed, 109 insertions(+), 73 deletions(-) diff --git a/app/controllers/api/v1/udt_queries_controller.rb b/app/controllers/api/v1/udt_queries_controller.rb index cdd934e39..252f8a3ea 100644 --- a/app/controllers/api/v1/udt_queries_controller.rb +++ b/app/controllers/api/v1/udt_queries_controller.rb @@ -4,7 +4,9 @@ class UdtQueriesController < ApplicationController def index udts = Udt.query_by_name_or_symbl(params[:q].downcase) - render json: UdtSerializer.new(udts, { fields: { udt: [:full_name, :symbol, :type_hash, :icon_file] } }) + render json: UdtSerializer.new(udts, + { fields: { udt: %i[full_name symbol + udt_type type_hash icon_file] } }) end end end diff --git a/app/serializers/udt_serializer.rb b/app/serializers/udt_serializer.rb index a359e63d2..20aa93b9c 100644 --- a/app/serializers/udt_serializer.rb +++ b/app/serializers/udt_serializer.rb @@ -2,7 +2,7 @@ class UdtSerializer include FastJsonapi::ObjectSerializer attributes :symbol, :full_name, :icon_file, :published, :description, - :type_hash, :type_script, :issuer_address, :display_name, :uan + :type_hash, :type_script, :issuer_address, :display_name, :uan, :udt_type attribute :total_amount do |object| object.total_amount.to_s diff --git a/test/controllers/api/v1/omiga_inscriptions_controller_test.rb b/test/controllers/api/v1/omiga_inscriptions_controller_test.rb index ba4d752ce..b0e20a6a0 100644 --- a/test/controllers/api/v1/omiga_inscriptions_controller_test.rb +++ b/test/controllers/api/v1/omiga_inscriptions_controller_test.rb @@ -46,7 +46,7 @@ class OmigaInscriptionsControllerTest < ActionDispatch::IntegrationTest assert_equal %w( symbol full_name display_name uan total_amount addresses_count decimal icon_file h24_ckb_transactions_count created_at description - published type_hash type_script issuer_address mint_status mint_limit expected_supply inscription_info_id + published type_hash type_script issuer_address mint_status mint_limit expected_supply inscription_info_id udt_type ).sort, response_udt["attributes"].keys.sort end diff --git a/test/controllers/api/v1/udt_queries_controller_test.rb b/test/controllers/api/v1/udt_queries_controller_test.rb index 1e9f82ef0..ac37ea905 100644 --- a/test/controllers/api/v1/udt_queries_controller_test.rb +++ b/test/controllers/api/v1/udt_queries_controller_test.rb @@ -21,10 +21,12 @@ class UdtQueriesControllerTest < ActionDispatch::IntegrationTest response_json = UdtSerializer.new([udt], { fields: { - udt: [ - :full_name, :symbol, :type_hash, - :icon_file - ] } }).serialized_json + udt: %i[ + full_name symbol udt_type type_hash + icon_file + ], + }, + }).serialized_json assert_response :success assert_equal response_json, response.body @@ -38,10 +40,12 @@ class UdtQueriesControllerTest < ActionDispatch::IntegrationTest response_json = UdtSerializer.new([udt], { fields: { - udt: [ - :full_name, :symbol, :type_hash, - :icon_file - ] } }).serialized_json + udt: %i[ + full_name symbol udt_type type_hash + icon_file + ], + }, + }).serialized_json assert_response :success assert_equal response_json, response.body @@ -56,10 +60,12 @@ class UdtQueriesControllerTest < ActionDispatch::IntegrationTest response_json = UdtSerializer.new([udt1, udt2], { fields: { - udt: [ - :full_name, :symbol, :type_hash, - :icon_file - ] } }).serialized_json + udt: %i[ + full_name symbol udt_type type_hash + icon_file + ], + }, + }).serialized_json assert_response :success assert_equal response_json, response.body diff --git a/test/controllers/api/v1/udts_controller_test.rb b/test/controllers/api/v1/udts_controller_test.rb index c55583487..f515bc07e 100644 --- a/test/controllers/api/v1/udts_controller_test.rb +++ b/test/controllers/api/v1/udts_controller_test.rb @@ -22,7 +22,8 @@ class UdtsControllerTest < ActionDispatch::IntegrationTest test "should respond with 415 Unsupported Media Type when Content-Type is wrong" do udt = create(:udt) - get api_v1_udt_url(udt.type_hash), headers: { "Content-Type": "text/plain" } + get api_v1_udt_url(udt.type_hash), + headers: { "Content-Type": "text/plain" } assert_equal 415, response.status end @@ -30,9 +31,11 @@ class UdtsControllerTest < ActionDispatch::IntegrationTest test "should respond with error object when Content-Type is wrong" do udt = create(:udt) error_object = Api::V1::Exceptions::InvalidContentTypeError.new - response_json = RequestErrorSerializer.new([error_object], message: error_object.title).serialized_json + response_json = RequestErrorSerializer.new([error_object], + message: error_object.title).serialized_json - get api_v1_udt_url(udt.type_hash), headers: { "Content-Type": "text/plain" } + get api_v1_udt_url(udt.type_hash), + headers: { "Content-Type": "text/plain" } assert_equal response_json, response.body end @@ -41,7 +44,8 @@ class UdtsControllerTest < ActionDispatch::IntegrationTest udt = create(:udt) get api_v1_udt_url(udt.type_hash), - headers: { "Content-Type": "application/vnd.api+json", "Accept": "application/json" } + headers: { "Content-Type": "application/vnd.api+json", + "Accept": "application/json" } assert_equal 406, response.status end @@ -49,17 +53,20 @@ class UdtsControllerTest < ActionDispatch::IntegrationTest test "should respond with error object when Accept is wrong" do udt = create(:udt) error_object = Api::V1::Exceptions::InvalidAcceptError.new - response_json = RequestErrorSerializer.new([error_object], message: error_object.title).serialized_json + response_json = RequestErrorSerializer.new([error_object], + message: error_object.title).serialized_json get api_v1_udt_url(udt.type_hash), - headers: { "Content-Type": "application/vnd.api+json", "Accept": "application/json" } + headers: { "Content-Type": "application/vnd.api+json", + "Accept": "application/json" } assert_equal response_json, response.body end test "should return error object when id is not a hex start with 0x" do error_object = Api::V1::Exceptions::TypeHashInvalidError.new - response_json = RequestErrorSerializer.new([error_object], message: error_object.title).serialized_json + response_json = RequestErrorSerializer.new([error_object], + message: error_object.title).serialized_json valid_get api_v1_udt_url("9034fwefwef") @@ -68,7 +75,8 @@ class UdtsControllerTest < ActionDispatch::IntegrationTest test "should return error object when id is a hex start with 0x but it's length is wrong" do error_object = Api::V1::Exceptions::TypeHashInvalidError.new - response_json = RequestErrorSerializer.new([error_object], message: error_object.title).serialized_json + response_json = RequestErrorSerializer.new([error_object], + message: error_object.title).serialized_json valid_get api_v1_udt_url("0x9034fwefwef") @@ -77,7 +85,8 @@ class UdtsControllerTest < ActionDispatch::IntegrationTest test "should return error object when no records found by id" do error_object = Api::V1::Exceptions::UdtNotFoundError.new - response_json = RequestErrorSerializer.new([error_object], message: error_object.title).serialized_json + response_json = RequestErrorSerializer.new([error_object], + message: error_object.title).serialized_json valid_get api_v1_udt_url("0x3b138b3126d10ec000417b68bc715f17e86293d6cdbcb3fd8a628ad4a0b756f6") @@ -87,7 +96,8 @@ class UdtsControllerTest < ActionDispatch::IntegrationTest test "should return error object when target udt is not published" do udt = create(:udt) error_object = Api::V1::Exceptions::UdtNotFoundError.new - response_json = RequestErrorSerializer.new([error_object], message: error_object.title).serialized_json + response_json = RequestErrorSerializer.new([error_object], + message: error_object.title).serialized_json valid_get api_v1_udt_url(udt.type_hash) @@ -111,7 +121,7 @@ class UdtsControllerTest < ActionDispatch::IntegrationTest assert_equal %w( symbol full_name display_name uan total_amount addresses_count decimal icon_file h24_ckb_transactions_count created_at description - published type_hash type_script issuer_address + published type_hash type_script issuer_address udt_type ).sort, response_tx_transaction["attributes"].keys.sort end @@ -136,7 +146,8 @@ class UdtsControllerTest < ActionDispatch::IntegrationTest test "should respond with error object when Content-Type is wrong when call index" do error_object = Api::V1::Exceptions::InvalidContentTypeError.new - response_json = RequestErrorSerializer.new([error_object], message: error_object.title).serialized_json + response_json = RequestErrorSerializer.new([error_object], + message: error_object.title).serialized_json get api_v1_udts_url, headers: { "Content-Type": "text/plain" } @@ -144,16 +155,21 @@ class UdtsControllerTest < ActionDispatch::IntegrationTest end test "should respond with 406 Not Acceptable when Accept is wrong when call index" do - get api_v1_udts_url, headers: { "Content-Type": "application/vnd.api+json", "Accept": "application/json" } + get api_v1_udts_url, + headers: { "Content-Type": "application/vnd.api+json", + "Accept": "application/json" } assert_equal 406, response.status end test "should respond with error object when Accept is wrong when call index" do error_object = Api::V1::Exceptions::InvalidAcceptError.new - response_json = RequestErrorSerializer.new([error_object], message: error_object.title).serialized_json + response_json = RequestErrorSerializer.new([error_object], + message: error_object.title).serialized_json - get api_v1_udts_url, headers: { "Content-Type": "application/vnd.api+json", "Accept": "application/json" } + get api_v1_udts_url, + headers: { "Content-Type": "application/vnd.api+json", + "Accept": "application/json" } assert_equal response_json, response.body end @@ -166,7 +182,8 @@ class UdtsControllerTest < ActionDispatch::IntegrationTest test "should return error object when page param is invalid" do error_object = Api::V1::Exceptions::PageParamError.new - response_json = RequestErrorSerializer.new([error_object], message: error_object.title).serialized_json + response_json = RequestErrorSerializer.new([error_object], + message: error_object.title).serialized_json valid_get api_v1_udts_url, params: { page: "aaa" } @@ -175,7 +192,8 @@ class UdtsControllerTest < ActionDispatch::IntegrationTest test "should return error object when page size param is invalid" do error_object = Api::V1::Exceptions::PageSizeParamError.new - response_json = RequestErrorSerializer.new([error_object], message: error_object.title).serialized_json + response_json = RequestErrorSerializer.new([error_object], + message: error_object.title).serialized_json valid_get api_v1_udts_url, params: { page_size: "aaa" } @@ -186,7 +204,8 @@ class UdtsControllerTest < ActionDispatch::IntegrationTest errors = [] errors << Api::V1::Exceptions::PageParamError.new errors << Api::V1::Exceptions::PageSizeParamError.new - response_json = RequestErrorSerializer.new(errors, message: errors.first.title).serialized_json + response_json = RequestErrorSerializer.new(errors, + message: errors.first.title).serialized_json valid_get api_v1_udts_url, params: { page: "bbb", page_size: "aaa" } @@ -207,10 +226,10 @@ class UdtsControllerTest < ActionDispatch::IntegrationTest page_size = 5 udts = Udt.sudt.order(id: :desc).page(page).per(page_size) - valid_get api_v1_udts_url, params: { page: page, page_size: page_size } + valid_get api_v1_udts_url, params: { page:, page_size: } - options = FastJsonapi::PaginationMetaGenerator.new(request: request, records: udts, page: page, - page_size: page_size).call + options = FastJsonapi::PaginationMetaGenerator.new(request:, records: udts, page:, + page_size:).call response_udts = UdtSerializer.new(udts, options).serialized_json assert_equal response_udts, response.body @@ -222,10 +241,10 @@ class UdtsControllerTest < ActionDispatch::IntegrationTest create_list(:udt, 10) udts = Udt.sudt.order(id: :desc).page(page).per(page_size) - valid_get api_v1_udts_url, params: { page: page, page_size: page_size } + valid_get api_v1_udts_url, params: { page:, page_size: } - options = FastJsonapi::PaginationMetaGenerator.new(request: request, records: udts, page: page, - page_size: page_size).call + options = FastJsonapi::PaginationMetaGenerator.new(request:, records: udts, page:, + page_size:).call response_udts = UdtSerializer.new(udts, options).serialized_json assert_equal response_udts, response.body @@ -239,10 +258,11 @@ class UdtsControllerTest < ActionDispatch::IntegrationTest end udts = Udt.sudt.order(h24_ckb_transactions_count: :asc).page(page).per(page_size) - valid_get api_v1_udts_url, params: { page: page, page_size: page_size, sort: "transactions" } + valid_get api_v1_udts_url, + params: { page:, page_size:, sort: "transactions" } - options = FastJsonapi::PaginationMetaGenerator.new(request: request, records: udts, page: page, - page_size: page_size).call + options = FastJsonapi::PaginationMetaGenerator.new(request:, records: udts, page:, + page_size:).call response_udts = UdtSerializer.new(udts, options).serialized_json assert_equal response_udts, response.body @@ -256,10 +276,11 @@ class UdtsControllerTest < ActionDispatch::IntegrationTest end udts = Udt.sudt.order(h24_ckb_transactions_count: :asc).page(page).per(page_size) - valid_get api_v1_udts_url, params: { page: page, page_size: page_size, sort: "transactions.asc" } + valid_get api_v1_udts_url, + params: { page:, page_size:, sort: "transactions.asc" } - options = FastJsonapi::PaginationMetaGenerator.new(request: request, records: udts, page: page, - page_size: page_size).call + options = FastJsonapi::PaginationMetaGenerator.new(request:, records: udts, page:, + page_size:).call response_udts = UdtSerializer.new(udts, options).serialized_json assert_equal response_udts, response.body @@ -273,10 +294,11 @@ class UdtsControllerTest < ActionDispatch::IntegrationTest end udts = Udt.sudt.order(h24_ckb_transactions_count: :asc).page(page).per(page_size) - valid_get api_v1_udts_url, params: { page: page, page_size: page_size, sort: "transactions.abcd" } + valid_get api_v1_udts_url, + params: { page:, page_size:, sort: "transactions.abcd" } - options = FastJsonapi::PaginationMetaGenerator.new(request: request, records: udts, page: page, - page_size: page_size).call + options = FastJsonapi::PaginationMetaGenerator.new(request:, records: udts, page:, + page_size:).call response_udts = UdtSerializer.new(udts, options).serialized_json assert_equal response_udts, response.body @@ -290,10 +312,11 @@ class UdtsControllerTest < ActionDispatch::IntegrationTest end udts = Udt.sudt.order(h24_ckb_transactions_count: :desc).page(page).per(page_size) - valid_get api_v1_udts_url, params: { page: page, page_size: page_size, sort: "transactions.desc" } + valid_get api_v1_udts_url, + params: { page:, page_size:, sort: "transactions.desc" } - options = FastJsonapi::PaginationMetaGenerator.new(request: request, records: udts, page: page, - page_size: page_size).call + options = FastJsonapi::PaginationMetaGenerator.new(request:, records: udts, page:, + page_size:).call response_udts = UdtSerializer.new(udts, options).serialized_json assert_equal response_udts, response.body @@ -308,10 +331,11 @@ class UdtsControllerTest < ActionDispatch::IntegrationTest end udts = Udt.sudt.order(block_timestamp: :asc).page(page).per(page_size) - valid_get api_v1_udts_url, params: { page: page, page_size: page_size, sort: "created_time" } + valid_get api_v1_udts_url, + params: { page:, page_size:, sort: "created_time" } - options = FastJsonapi::PaginationMetaGenerator.new(request: request, records: udts, page: page, - page_size: page_size).call + options = FastJsonapi::PaginationMetaGenerator.new(request:, records: udts, page:, + page_size:).call response_udts = UdtSerializer.new(udts, options).serialized_json assert_equal response_udts, response.body @@ -325,10 +349,11 @@ class UdtsControllerTest < ActionDispatch::IntegrationTest end udts = Udt.sudt.order(addresses_count: :asc).page(page).per(page_size) - valid_get api_v1_udts_url, params: { page: page, page_size: page_size, sort: "addresses_count" } + valid_get api_v1_udts_url, + params: { page:, page_size:, sort: "addresses_count" } - options = FastJsonapi::PaginationMetaGenerator.new(request: request, records: udts, page: page, - page_size: page_size).call + options = FastJsonapi::PaginationMetaGenerator.new(request:, records: udts, page:, + page_size:).call response_udts = UdtSerializer.new(udts, options).serialized_json assert_equal response_udts, response.body @@ -369,7 +394,7 @@ class UdtsControllerTest < ActionDispatch::IntegrationTest get download_csv_api_v1_udts_url(id: udt.type_hash), headers: { "Content-Type": "application/vnd.api+json", - "Accept": "application/json" + "Accept": "application/json", } assert_equal 406, response.status @@ -384,7 +409,7 @@ class UdtsControllerTest < ActionDispatch::IntegrationTest get download_csv_api_v1_udts_url(id: udt.type_hash), headers: { "Content-Type": "application/vnd.api+json", - "Accept": "application/json" + "Accept": "application/json", } assert_equal response_json, response.body @@ -392,7 +417,8 @@ class UdtsControllerTest < ActionDispatch::IntegrationTest test "should return error object when call download csv id is not a type hash" do error_object = Api::V1::Exceptions::UdtNotFoundError.new - response_json = RequestErrorSerializer.new([error_object], message: error_object.title).serialized_json + response_json = RequestErrorSerializer.new([error_object], + message: error_object.title).serialized_json valid_get download_csv_api_v1_udts_url(id: "9034fwefwef") @@ -428,7 +454,7 @@ class UdtsControllerTest < ActionDispatch::IntegrationTest icon_file: "https://img.udt.img", uan: "GWK.gw|gb.ckb", display_name: "GodwokenToken (via Godwoken Bridge from CKB)", - email: "contact@usdt.com" + email: "contact@usdt.com", } assert_response :success @@ -437,11 +463,13 @@ class UdtsControllerTest < ActionDispatch::IntegrationTest assert_equal udt.full_name, "GodwokenToken on testnet_v1" assert_equal udt.decimal, 8 assert_equal udt.total_amount, 100000000000 - assert_equal udt.description, "The sUDT_ERC20_Proxy of Godwoken Test Token." + assert_equal udt.description, + "The sUDT_ERC20_Proxy of Godwoken Test Token." assert_equal udt.operator_website, "https://udt.coin" assert_equal udt.icon_file, "https://img.udt.img" assert_equal udt.uan, "GWK.gw|gb.ckb" - assert_equal udt.display_name, "GodwokenToken (via Godwoken Bridge from CKB)" + assert_equal udt.display_name, + "GodwokenToken (via Godwoken Bridge from CKB)" assert_equal udt.email, "contact@usdt.com" end @@ -456,7 +484,7 @@ class UdtsControllerTest < ActionDispatch::IntegrationTest operator_website: "https://udt.coin", icon_file: "https://img.udt.img", uan: "GWK.gw|gb.ckb", - display_name: "GodwokenToken (via Godwoken Bridge from CKB)" + display_name: "GodwokenToken (via Godwoken Bridge from CKB)", } assert_equal 400, response.status @@ -477,7 +505,7 @@ class UdtsControllerTest < ActionDispatch::IntegrationTest icon_file: "https://img.udt.img", uan: "GWK.gw|gb.ckb", display_name: "GodwokenToken (via Godwoken Bridge from CKB)", - email: "abcdefg" + email: "abcdefg", } assert_equal 400, response.status @@ -497,7 +525,7 @@ class UdtsControllerTest < ActionDispatch::IntegrationTest operator_website: "https://udt.coin", icon_file: "https://img.udt.img", uan: "GWK.gw|gb.ckb", - display_name: "GodwokenToken (via Godwoken Bridge from CKB)" + display_name: "GodwokenToken (via Godwoken Bridge from CKB)", } assert_equal 404, response.status @@ -510,7 +538,7 @@ class UdtsControllerTest < ActionDispatch::IntegrationTest valid_put api_v1_udt_url("#{udt.type_hash}"), params: { symbol: "GWK", full_name: "GodwokenToken on testnet_v1", - token: "123456" + token: "123456", } assert_equal 404, response.status @@ -520,12 +548,12 @@ class UdtsControllerTest < ActionDispatch::IntegrationTest test "raise udt_verification expired error when update udt" do udt = create(:udt, email: "abc@sudt.com", published: true) - create(:udt_verification, sent_at: Time.now - 11.minutes, udt: udt) + create(:udt_verification, sent_at: Time.now - 11.minutes, udt:) valid_put api_v1_udt_url("#{udt.type_hash}"), params: { symbol: "GWK", full_name: "GodwokenToken on testnet_v1", total_amount: "100000000", - token: "123456" + token: "123456", } assert_equal 400, response.status @@ -535,12 +563,12 @@ class UdtsControllerTest < ActionDispatch::IntegrationTest test "raise udt_verification token not match error when update udt" do udt = create(:udt, email: "abc@sudt.com", published: true) - create(:udt_verification, udt: udt) + create(:udt_verification, udt:) valid_put api_v1_udt_url("#{udt.type_hash}"), params: { symbol: "GWK", full_name: "GodwokenToken on testnet_v1", total_amount: "100000000", - token: "123" + token: "123", } assert_equal 400, response.status @@ -550,12 +578,12 @@ class UdtsControllerTest < ActionDispatch::IntegrationTest test "should update successfully when update udt" do udt = create(:udt, email: "abc@sudt.com") - create(:udt_verification, udt: udt) + create(:udt_verification, udt:) valid_put api_v1_udt_url("#{udt.type_hash}"), params: { symbol: "GWK", full_name: "GodwokenToken on testnet_v1", total_amount: "100000000", - token: "123456" + token: "123456", } assert_equal 200, response.status