From d8c479b241792b839c8fcc6627b5c69917ee919b Mon Sep 17 00:00:00 2001 From: Miles Zhang Date: Mon, 22 Jan 2024 11:02:29 +0800 Subject: [PATCH] Issue 508 14 (#1600) * feat: record pre udt_hash to new rebase start omiga inscription Signed-off-by: Miles Zhang * feat: adjust omiga_inscription api to handle with same info type hash Signed-off-by: Miles Zhang * test: fix test Signed-off-by: Miles Zhang --------- Signed-off-by: Miles Zhang --- .../api/v1/omiga_inscriptions_controller.rb | 26 ++++++++-- ...port_omiga_inscription_transactions_job.rb | 13 +++-- .../ckb_sync/new_node_data_processor.rb | 31 ++++++------ app/models/omiga_inscription_info.rb | 1 + app/serializers/udt_serializer.rb | 6 +++ ..._pre_udt_hash_to_omiga_inscription_info.rb | 5 ++ db/structure.sql | 6 ++- .../v1/omiga_inscriptions_controller_test.rb | 42 ++++++++++++++++- test/factories/omiga_inscription_info.rb | 14 +++++- .../ckb_sync/node_data_processor_test.rb | 47 +++++++++++++++++++ vcr_fixtures/vcr_cassettes/blocks/33.yml | 39 +++++++++++++++ 11 files changed, 202 insertions(+), 28 deletions(-) create mode 100644 db/migrate/20240119131328_add_pre_udt_hash_to_omiga_inscription_info.rb create mode 100644 vcr_fixtures/vcr_cassettes/blocks/33.yml diff --git a/app/controllers/api/v1/omiga_inscriptions_controller.rb b/app/controllers/api/v1/omiga_inscriptions_controller.rb index 950a64655..44f1e95ec 100644 --- a/app/controllers/api/v1/omiga_inscriptions_controller.rb +++ b/app/controllers/api/v1/omiga_inscriptions_controller.rb @@ -6,7 +6,15 @@ class OmigaInscriptionsController < ApplicationController only: :index def index - udts = Udt.omiga_inscription + pre_udt_hashes = OmigaInscriptionInfo.where.not(pre_udt_hash: nil).pluck(:pre_udt_hash) + udts = + if pre_udt_hashes.present? + Udt.joins(:omiga_inscription_info).where.not( + "omiga_inscription_infos.mint_status = 1 and omiga_inscription_infos.udt_hash IN (?)", pre_udt_hashes + ) + else + Udt.omiga_inscription + end if stale?(udts) udts = sort_udts(udts).page(@page).per(@page_size).fast_page @@ -22,9 +30,17 @@ def index end def show - udt = Udt.joins(:omiga_inscription_info).where( - "udts.type_hash = ? or omiga_inscription_infos.type_hash = ?", params[:id], params[:id] - ).first + udt = + if params[:status] == "closed" + Udt.joins(:omiga_inscription_info).where( + "omiga_inscription_infos.type_hash = ? and omiga_inscription_infos.mint_status = 1", params[:id] + ).first + else + Udt.joins(:omiga_inscription_info).where( + "udts.type_hash = ? or omiga_inscription_infos.type_hash = ?", params[:id], params[:id] + ).order("id DESC").first + end + if udt.nil? raise Api::V1::Exceptions::UdtNotFoundError else @@ -34,7 +50,7 @@ def show def download_csv args = params.permit(:id, :start_date, :end_date, :start_number, - :end_number, udt: {}) + :end_number, :status, udt: {}) file = CsvExportable::ExportOmigaInscriptionTransactionsJob.perform_now(args.to_h) send_data file, type: "text/csv; charset=utf-8; header=present", diff --git a/app/jobs/csv_exportable/export_omiga_inscription_transactions_job.rb b/app/jobs/csv_exportable/export_omiga_inscription_transactions_job.rb index 036f179fc..343b1f003 100644 --- a/app/jobs/csv_exportable/export_omiga_inscription_transactions_job.rb +++ b/app/jobs/csv_exportable/export_omiga_inscription_transactions_job.rb @@ -1,9 +1,16 @@ module CsvExportable class ExportOmigaInscriptionTransactionsJob < BaseExporter def perform(args) - udt = Udt.joins(:omiga_inscription_info).where( - "udts.type_hash = ? or omiga_inscription_infos.type_hash = ?", args[:id], args[:id] - ).first + udt = + if args[:status] == "closed" + Udt.joins(:omiga_inscription_info).where( + "omiga_inscription_infos.type_hash = ? and omiga_inscription_infos.mint_status = 1", args[:id] + ).first + else + Udt.joins(:omiga_inscription_info).where( + "udts.type_hash = ? or omiga_inscription_infos.type_hash = ?", args[:id], args[:id] + ).order("id DESC").first + end ckb_transactions = udt.ckb_transactions if args[:start_date].present? diff --git a/app/models/ckb_sync/new_node_data_processor.rb b/app/models/ckb_sync/new_node_data_processor.rb index c6c180db3..8eb7ef38b 100644 --- a/app/models/ckb_sync/new_node_data_processor.rb +++ b/app/models/ckb_sync/new_node_data_processor.rb @@ -514,14 +514,7 @@ def update_or_create_udt_accounts!(local_block) end def udt_type(cell_type) - case cell_type - when "udt" - "sudt" - when "omiga_inscription_info" - "omiga_inscription" - else - cell_type - end + cell_type == "udt" ? "sudt" : cell_type end def udt_account_amount(udt_type, type_hash, address) @@ -629,16 +622,24 @@ def build_udts!(local_block, outputs, outputs_data) next unless cell_type.in?(%w(udt m_nft_token nrc_721_token spore_cell omiga_inscription_info omiga_inscription)) - type_hash = + type_hash, parsed_udt_type = 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, - type_hash: output.type.compute_hash), unique_by: :udt_hash + info_type_hash = output.type.compute_hash + attrs = info.merge(output.type.to_h, type_hash: info_type_hash) + pre_closed_info = OmigaInscriptionInfo.find_by( + type_hash: info_type_hash, mint_status: :closed, ) - info[:udt_hash] + attrs = + if pre_closed_info + attrs.merge(pre_udt_hash: pre_closed_info.udt_hash) + else + attrs + end + OmigaInscriptionInfo.upsert(attrs, unique_by: :udt_hash) + [info[:udt_hash], "omiga_inscription"] else - output.type.compute_hash + [output.type.compute_hash, udt_type(cell_type)] end if cell_type == "omiga_inscription" @@ -714,7 +715,7 @@ def build_udts!(local_block, outputs, outputs_data) end # fill issuer_address after publish the token udts_attributes << { - type_hash:, udt_type: udt_type(cell_type), block_timestamp: local_block.timestamp, args: output.type.args, + type_hash:, udt_type: parsed_udt_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) end diff --git a/app/models/omiga_inscription_info.rb b/app/models/omiga_inscription_info.rb index 5a82ec3e7..98cdb2550 100644 --- a/app/models/omiga_inscription_info.rb +++ b/app/models/omiga_inscription_info.rb @@ -23,6 +23,7 @@ class OmigaInscriptionInfo < ApplicationRecord # created_at :datetime not null # updated_at :datetime not null # type_hash :binary +# pre_udt_hash :binary # # Indexes # diff --git a/app/serializers/udt_serializer.rb b/app/serializers/udt_serializer.rb index 4afa982fc..223dc8f17 100644 --- a/app/serializers/udt_serializer.rb +++ b/app/serializers/udt_serializer.rb @@ -49,4 +49,10 @@ class UdtSerializer } do |object| object.omiga_inscription_info.type_hash end + + attribute :pre_udt_hash, if: Proc.new { |record, _params| + record.udt_type == "omiga_inscription" + } do |object| + object.omiga_inscription_info.pre_udt_hash + end end diff --git a/db/migrate/20240119131328_add_pre_udt_hash_to_omiga_inscription_info.rb b/db/migrate/20240119131328_add_pre_udt_hash_to_omiga_inscription_info.rb new file mode 100644 index 000000000..c14765135 --- /dev/null +++ b/db/migrate/20240119131328_add_pre_udt_hash_to_omiga_inscription_info.rb @@ -0,0 +1,5 @@ +class AddPreUdtHashToOmigaInscriptionInfo < ActiveRecord::Migration[7.0] + def change + add_column :omiga_inscription_infos, :pre_udt_hash, :binary + end +end diff --git a/db/structure.sql b/db/structure.sql index d71619f8b..a0e72caf9 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -1669,7 +1669,8 @@ CREATE TABLE public.omiga_inscription_infos ( udt_id bigint, created_at timestamp(6) without time zone NOT NULL, updated_at timestamp(6) without time zone NOT NULL, - type_hash bytea + type_hash bytea, + pre_udt_hash bytea ); @@ -4818,6 +4819,7 @@ INSERT INTO "schema_migrations" (version) VALUES ('20231017074221'), ('20231218082938'), ('20240107100346'), -('20240118103947'); +('20240118103947'), +('20240119131328'); diff --git a/test/controllers/api/v1/omiga_inscriptions_controller_test.rb b/test/controllers/api/v1/omiga_inscriptions_controller_test.rb index bb7b1fc72..0c025569f 100644 --- a/test/controllers/api/v1/omiga_inscriptions_controller_test.rb +++ b/test/controllers/api/v1/omiga_inscriptions_controller_test.rb @@ -11,6 +11,32 @@ class OmigaInscriptionsControllerTest < ActionDispatch::IntegrationTest assert_response :success end + test "should return pre udt when call show" do + udt = create(:udt, :omiga_inscription) + udt.omiga_inscription_info.update(mint_status: :closed) + new_udt = create(:udt, udt_type: :omiga_inscription) + info = create(:omiga_inscription_info, udt_id: new_udt.id, + mint_status: :rebase_start, pre_udt_hash: udt.omiga_inscription_info.udt_hash, udt_hash: "0x#{SecureRandom.hex(32)}") + + valid_get api_v1_omiga_inscription_url(info.type_hash, status: "closed") + assert_equal udt.type_hash, + JSON.parse(response.body)["data"]["attributes"]["type_hash"] + end + + test "should return current rebase_start udt when call show" do + udt = create(:udt, :omiga_inscription, + block_timestamp: (Time.now - 10.minutes).to_i * 1000) + udt.omiga_inscription_info.update(mint_status: :closed) + new_udt = create(:udt, udt_type: :omiga_inscription, + block_timestamp: Time.now.to_i * 1000) + info = create(:omiga_inscription_info, udt_id: new_udt.id, + mint_status: :rebase_start, pre_udt_hash: udt.omiga_inscription_info.udt_hash, udt_hash: "0x#{SecureRandom.hex(32)}") + + valid_get api_v1_omiga_inscription_url(info.type_hash) + assert_equal new_udt.type_hash, + JSON.parse(response.body)["data"]["attributes"]["type_hash"] + end + test "should set right content type when call show" do udt = create(:udt, :omiga_inscription) @@ -46,7 +72,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 udt_type info_type_hash + published type_hash type_script issuer_address mint_status mint_limit expected_supply inscription_info_id udt_type pre_udt_hash info_type_hash ).sort, response_udt["attributes"].keys.sort end @@ -60,7 +86,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 udt_type info_type_hash + published type_hash type_script issuer_address mint_status mint_limit expected_supply inscription_info_id udt_type pre_udt_hash info_type_hash ).sort, response_udt["attributes"].keys.sort end @@ -89,6 +115,18 @@ class OmigaInscriptionsControllerTest < ActionDispatch::IntegrationTest assert_equal 2, json["data"].length end + test "should return rebase_start omiga_inscription udts" do + udt = create(:udt, :omiga_inscription) + udt.omiga_inscription_info.update(mint_status: :closed) + new_udt = create(:udt, udt_type: :omiga_inscription) + create(:omiga_inscription_info, udt_id: new_udt.id, + mint_status: :rebase_start, pre_udt_hash: udt.omiga_inscription_info.udt_hash, udt_hash: "0x#{SecureRandom.hex(32)}") + + valid_get api_v1_omiga_inscriptions_url + + assert_equal 1, json["data"].length + end + test "should sorted by mint_status asc when sort param is mint_status" do page = 1 page_size = 5 diff --git a/test/factories/omiga_inscription_info.rb b/test/factories/omiga_inscription_info.rb index cd03b64e9..dab220064 100644 --- a/test/factories/omiga_inscription_info.rb +++ b/test/factories/omiga_inscription_info.rb @@ -1,5 +1,17 @@ FactoryBot.define do factory :omiga_inscription_info do - udt_hash { "0x#{SecureRandom.hex(32)}" } + udt_hash do + "0x5fa66c8d5f43914f85d3083e0529931883a5b0a14282f891201069f1b5067908" + end + code_hash do + "0x50fdea2d0030a8d0b3d69f883b471cab2a29cae6f01923f19cecac0f27fdaaa6" + end + hash_type { "type" } + args do + "0xcd89d8f36593a9a82501c024c5cdc4877ca11c5b3d5831b3e78334aecb978f0d" + end + type_hash do + "0x5cfcab1fc499de7d33265b04d2de9cf2f91cc7c7a578642993b0912b31b6cf39" + 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 f8037850d..68d49aefc 100644 --- a/test/models/ckb_sync/node_data_processor_test.rb +++ b/test/models/ckb_sync/node_data_processor_test.rb @@ -4101,6 +4101,53 @@ class NodeDataProcessorTest < ActiveSupport::TestCase end end + test "change omiga inscription to rebase_start" do + CkbSync::Api.any_instance.stubs(:mode).returns("testnet") + 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/33") do + node_block = CkbSync::Api.instance.get_block_by_number(33) + 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: "omiga_inscription_info", + lock_script_id: address1_lock.id, + type_script_id: nil) + + udt = create(:udt, code_hash: "0x25c29dc317811a6f6f3985a7a9ebc4838bd388d19d0feeecf0bcd60f6c0975bb", hash_type: "type", args: "0x9709d30fc21348ae1d28a197310a80aec3b8cdb5c93814d5e240f9fba85b76af", + type_hash: "0x5fa66c8d5f43914f85d3083e0529931883a5b0a14282f891201069f1b5067908", udt_type: "omiga_inscription") + info = create(:omiga_inscription_info, + code_hash: "0x50fdea2d0030a8d0b3d69f883b471cab2a29cae6f01923f19cecac0f27fdaaa6", + hash_type: "type", + args: "0xcd89d8f36593a9a82501c024c5cdc4877ca11c5b3d5831b3e78334aecb978f0d", + type_hash: "0x5cfcab1fc499de7d33265b04d2de9cf2f91cc7c7a578642993b0912b31b6cf39", + decimal: 0.8e1, + name: "CKB Fist Inscription", + symbol: "CKBI", + udt_hash: "0x5fa66c8d5f43914f85d3083e0529931883a5b0a14282f891201069f1b5067908", + expected_supply: 0.21e16, + mint_limit: 0.1e12, + mint_status: "closed", + udt_id: udt.id) + + node_data_processor.process_block(node_block) + assert_equal 2, Udt.count + assert_equal info.udt_hash, OmigaInscriptionInfo.last.pre_udt_hash + end + end + private def node_data_processor diff --git a/vcr_fixtures/vcr_cassettes/blocks/33.yml b/vcr_fixtures/vcr_cassettes/blocks/33.yml new file mode 100644 index 000000000..d5f9c3b4e --- /dev/null +++ b/vcr_fixtures/vcr_cassettes/blocks/33.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":["0x21","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":"0xa33703945490c0d8eb61dd564dcdce04d6ad80a8ae1aeef671354f9735ec74bb","header":{"compact_target":"0x1d08cdb1","dao":"0x4462198b0e5d5c4aad67c38868c82700749fdc3d3514d80500ec69f6012acf08","epoch":"0x70803ee001ed5","extra_hash":"0x7f28e2900ffc36be0bcbe76253ec558d5c2ce1868ba029438d7a39f514078056","hash":"0x1dcad92e8085f70ed8dc7eb3c105dbae84bd267f4f426cf265f9d959436a1287","nonce":"0x6691cc8bd17283f67f35b2bdf31fad91","number":"0x21","parent_hash":"0x96f44bbc683837c917066f7b610a6709b629604bb4a544293f45e522ae57e4b3","proposals_hash":"0x297d92aff8d62ba05f067085afe1082bc8b080883f27cfcd440be1bea1a5433e","timestamp":"0x18cba8806b7","transactions_root":"0x171dbdcf5572615f2c111f9fd3eef00304f25f482b0f1bf141bb7b742769a136","version":"0x0"},"proposals":["0xe7989e121502a9c906d1","0xb31087bf0881f23574b0"],"transactions":[{"cell_deps":[],"hash":"0xe150a92d7a15f9f85bc0fd806885b012b1c084728ef6c0f1af157fad59814f3c","header_deps":[],"inputs":[{"previous_output":{"index":"0xffffffff","tx_hash":"0x0000000000000000000000000000000000000000000000000000000000000000"},"since":"0xb3bf47"}],"outputs":[{"capacity":"0x19bf50f9db","lock":{"args":"0x0450340178ae277261a838c89f9ccb76a190ed4b","code_hash":"0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8","hash_type":"type"},"type":null}],"outputs_data":["0x"],"version":"0x0","witnesses":["0x830000000c00000055000000490000001000000030000000310000009bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce80114000000da648442dbb7347e467d1d09da13e5cd3a0ef0e12a0000000000000020302e3131332e302d72633220283866663030323620323032332d31322d31392920deadbeef"]},{"cell_deps":[{"dep_type":"dep_group","out_point":{"index":"0x0","tx_hash":"0x4dcf3f3b09efac8995d6cbee87c5345e812d310094651e0c3d9a730f32dc9263"}},{"dep_type":"code","out_point":{"index":"0x0","tx_hash":"0x7bf3899cf41879ed0319bf5312c9db5bf5620fff9ebe59556c261c48f0369054"}}],"hash":"0x7046d8c5641f0cfa22bf4b2905bd4fb0e619e42bc008130a8dc743d2959fef3b","header_deps":[],"inputs":[{"previous_output":{"index":"0x1","tx_hash":"0x3e89753ebca825e1504498eb18b56576d5b7eff59fe033346a10ab9e8ca359a4"},"since":"0x0"}],"outputs":[{"capacity":"0x525430e20","lock":{"args":"0x00016091d93dbab12f16640fb3a0a8f1e77e03fbc51c","code_hash":"0xd23761b364210735c19c60561d213fb3beae2fd6172743719eff6920e020baac","hash_type":"type"},"type":{"args":"0xcd89d8f36593a9a82501c024c5cdc4877ca11c5b3d5831b3e78334aecb978f0d","code_hash":"0x50fdea2d0030a8d0b3d69f883b471cab2a29cae6f01923f19cecac0f27fdaaa6","hash_type":"type"}}],"outputs_data":["0x0814434b42204669737420496e736372697074696f6e04434b4249a69f54bf339dd121febe64cb0be3a2cf366a8b13ec1a5ae4bebdccb9039c7efa0040075af0750700000000000000000000e8764817000000000000000000000002"],"version":"0x0","witnesses":["0x6b010000100000006b0100006b01000057010000014599a5795423d54ab8e1f44f5c6ef5be9b1829beddb787bc732e4469d25f8c93e94afa393617f905bf1765c35dc38501a862b4b2f794a88b4f9010da02411a85e201947f9c04ff5ca1b92412f11a28d74c48339e48a192d8327738515469a877475fcd3b47c81e7d026d30b853e12bb250779a999f0aba1057e9add098f713f749960de5880e8c687434170f6476605b8fe4aeb9a28632c7995cf3ba831d97630162f9fb777b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a22596a56694d7a45325a6d5a694e4749774d3259314e474d795a6d51355a445978595756694f5745774f5455334f444a6b5a6d526a5a544a6c4d545a6d5a4755315a6a45345a4759314d4451354f4459355a6a45785967222c226f726967696e223a22687474703a2f2f6c6f63616c686f73743a38303030222c2263726f73734f726967696e223a66616c73657d"]}],"uncles":[]},"id":2} + ' + http_version: + recorded_at: Fri, 04 Oct 2019 15:54:13 GMT +recorded_with: VCR 5.0.0