From 892201287c44016ceb7b704d1e046fd4cd72cb93 Mon Sep 17 00:00:00 2001 From: Miles Zhang Date: Fri, 2 Aug 2024 10:31:37 +0800 Subject: [PATCH 1/3] feat: adjust xudt and nft tag logic (#2084) * feat: adjust xudt and nft tag logic Signed-off-by: Miles Zhang * fix: lp token issuer address logic Signed-off-by: Miles Zhang * feat: nft tag renmae rgbpp-compatible to rgb++ Signed-off-by: Miles Zhang * fix: typo Signed-off-by: Miles Zhang * test: fix xudt_tag worker test Signed-off-by: Miles Zhang * feat: nft name out-of-length tag max 60 characters Signed-off-by: Miles Zhang --------- Signed-off-by: Miles Zhang --- .../ckb_sync/new_node_data_processor.rb | 4 ++- app/models/token_collection.rb | 2 +- app/models/xudt_tag.rb | 2 +- app/workers/token_collection_tag_worker.rb | 14 +++------- app/workers/xudt_tag_worker.rb | 21 ++++++++------ .../api/v2/nft/collections_controller_test.rb | 10 +++---- .../token_collection_tag_worker_test.rb | 13 ++++----- test/workers/xudt_tag_worker_test.rb | 28 ++++++++++++------- 8 files changed, 49 insertions(+), 45 deletions(-) diff --git a/app/models/ckb_sync/new_node_data_processor.rb b/app/models/ckb_sync/new_node_data_processor.rb index 0a2d04e0a..02597b151 100644 --- a/app/models/ckb_sync/new_node_data_processor.rb +++ b/app/models/ckb_sync/new_node_data_processor.rb @@ -671,7 +671,9 @@ def build_udts!(local_block, outputs, outputs_data) nft_token_attr[:decimal] = info[:decimal] nft_token_attr[:published] = true when "xudt", "xudt_compatible" - issuer_address = Address.find_by(lock_hash: output.type.args[0..65])&.address_hash + if output.type.args.length == 66 + issuer_address = Address.find_by(lock_hash: output.type.args[0..65])&.address_hash + end items.each_with_index do |output, index| if output.type&.code_hash == CkbSync::Api.instance.unique_cell_code_hash info = CkbUtils.parse_unique_cell(outputs_data[tx_index][index]) diff --git a/app/models/token_collection.rb b/app/models/token_collection.rb index 6fa7d8b43..3bff9f90e 100644 --- a/app/models/token_collection.rb +++ b/app/models/token_collection.rb @@ -1,5 +1,5 @@ class TokenCollection < ApplicationRecord - VALID_TAGS = ["invalid", "suspicious", "out-of-length-range", "rgbpp-compatible", "layer-1-asset", "duplicate", "layer-2-asset"] + VALID_TAGS = ["invalid", "suspicious", "out-of-length-range", "rgb++", "layer-1-asset", "layer-2-asset"] enum standard: { cota: "cota", spore: "spore", m_nft: "m_nft", nrc721: "nrc721" } diff --git a/app/models/xudt_tag.rb b/app/models/xudt_tag.rb index 3ec66726e..a2d226b2e 100644 --- a/app/models/xudt_tag.rb +++ b/app/models/xudt_tag.rb @@ -1,7 +1,7 @@ class XudtTag < ApplicationRecord belongs_to :udt - VALID_TAGS = ["unnamed", "invalid", "suspicious", "out-of-length-range", "rgbpp-compatible", "layer-1-asset", "supply-limited", "duplicate", "layer-2-asset", "supply-unlimited"] + VALID_TAGS = ["unnamed", "invalid", "suspicious", "out-of-length-range", "rgb++", "layer-1-asset", "supply-limited", "utility", "layer-2-asset", "supply-unlimited"] end # == Schema Information diff --git a/app/workers/token_collection_tag_worker.rb b/app/workers/token_collection_tag_worker.rb index d03a4191f..e30b00525 100644 --- a/app/workers/token_collection_tag_worker.rb +++ b/app/workers/token_collection_tag_worker.rb @@ -21,16 +21,10 @@ def mark_tags(token_collection) ["suspicious"] elsif out_of_length?(token_collection.name) ["out-of-length-range"] - elsif first_token_collection?(token_collection.name, token_collection.block_timestamp, token_collection.standard) - if rgbpp_lock?(token_collection.creator.address_hash) - ["rgbpp-compatible", "layer-1-asset"] - else - ["rgbpp-compatible", "layer-2-asset"] - end elsif rgbpp_lock?(token_collection.creator.address_hash) - ["duplicate", "layer-1-asset"] + ["rgb++", "layer-1-asset"] else - ["duplicate", "layer-2-asset"] + ["rgb++", "layer-2-asset"] end end @@ -39,11 +33,11 @@ def invalid_char?(name) end def invisible_char?(name) - (name =~ /^[\x21-\x7E]+$/).nil? + (name =~ /^[\x21-\x7E]+(?:\s[\x21-\x7E]+)?$/).nil? end def out_of_length?(name) - name.length > 255 + name.length > 60 end def first_token_collection?(name, block_timestamp, standard) diff --git a/app/workers/xudt_tag_worker.rb b/app/workers/xudt_tag_worker.rb index f38168cd5..cb0b25bd2 100644 --- a/app/workers/xudt_tag_worker.rb +++ b/app/workers/xudt_tag_worker.rb @@ -7,6 +7,7 @@ def perform attrs = udts.map do |udt| tags = mark_tags(udt) + tags << "rgb++" if udt.xudt? && !tags.include?("rgb++") { udt_id: udt.id, udt_type_hash: udt.type_hash, tags: } end @@ -23,16 +24,14 @@ def mark_tags(udt) ["suspicious"] elsif out_of_length?(udt.symbol) ["out-of-length-range"] - elsif first_xudt?(udt.symbol, udt.block_timestamp) - if rgbpp_lock?(udt.issuer_address) - ["rgbpp-compatible", "layer-1-asset", "supply-limited"] - else - ["rgbpp-compatible", "layer-2-asset", "supply-unlimited"] - end + elsif utility_lp_token?(udt.args) + ["utility"] + elsif !first_xudt?(udt.symbol, udt.block_timestamp) + ["suspicious"] elsif rgbpp_lock?(udt.issuer_address) - ["duplicate", "layer-1-asset", "supply-limited"] + ["rgb++", "layer-1-asset", "supply-limited"] else - ["duplicate", "layer-2-asset", "supply-unlimited"] + ["rgb++", "layer-2-asset", "supply-unlimited"] end end @@ -41,7 +40,7 @@ def invalid_char?(symbol) end def invisible_char?(symbol) - (symbol =~ /^[\x21-\x7E]+$/).nil? + (symbol =~ /^[\x21-\x7E]+(?:\s[\x21-\x7E]+)?$/).nil? end def out_of_length?(symbol) @@ -57,6 +56,10 @@ def rgbpp_lock?(issuer_address) issuer_address.present? && CkbSync::Api.instance.rgbpp_code_hash.include?(address_code_hash) end + def utility_lp_token?(args) + args.length == 74 + end + ## TODO: current no this condition def omni_lock_with_supply_mode?(issuer_address); end end diff --git a/test/controllers/api/v2/nft/collections_controller_test.rb b/test/controllers/api/v2/nft/collections_controller_test.rb index 80f5c7a7a..9df694219 100644 --- a/test/controllers/api/v2/nft/collections_controller_test.rb +++ b/test/controllers/api/v2/nft/collections_controller_test.rb @@ -14,17 +14,17 @@ class NFT::CollectionsControllerTest < ActionDispatch::IntegrationTest end test "should filter by union tags" do - create :token_collection, name: "token1", tags: ["layer-1-asset", "rgbpp-compatible"] - create :token_collection, name: "token2", tags: ["layer-1-asset", "rgbpp-compatible"] + create :token_collection, name: "token1", tags: ["layer-1-asset", "rgb++"] + create :token_collection, name: "token2", tags: ["layer-1-asset", "rgb++"] - get api_v2_nft_collections_url, params: { tags: "layer-1-asset,rgbpp-compatible", union: true } + get api_v2_nft_collections_url, params: { tags: "layer-1-asset,rgb++", union: true } assert_response :success assert_equal JSON.parse(response.body)["data"].size, 2 end test "should filter by tags but not match" do - create :token_collection, name: "token1", tags: ["layer-1-asset", "rgbpp-compatible"] - create :token_collection, name: "token2", tags: ["layer-1-asset", "rgbpp-compatible"] + create :token_collection, name: "token1", tags: ["layer-1-asset", "rgb++"] + create :token_collection, name: "token2", tags: ["layer-1-asset", "rgb++"] get api_v2_nft_collections_url, params: { tags: "layer-1-asset,invalid" } assert_response :success diff --git a/test/workers/token_collection_tag_worker_test.rb b/test/workers/token_collection_tag_worker_test.rb index 127ae21b5..6c652abd5 100644 --- a/test/workers/token_collection_tag_worker_test.rb +++ b/test/workers/token_collection_tag_worker_test.rb @@ -14,23 +14,20 @@ class TokenCollectionTagWorkerTest < ActiveJob::TestCase end test "add suspicious tag to token_collection" do - create(:token_collection, name: "CK BB", cell_id: @cell.id, creator_id: @address.id) + create(:token_collection, name: "CK BB", cell_id: @cell.id, creator_id: @address.id) TokenCollectionTagWorker.new.perform assert_equal ["suspicious"], TokenCollection.last.tags end test "add out-of-length-range tag to token_collection" do - create(:token_collection, name: "C" * 256, cell_id: @cell.id, creator_id: @address.id) + create(:token_collection, name: "C" * 66, cell_id: @cell.id, creator_id: @address.id) TokenCollectionTagWorker.new.perform assert_equal ["out-of-length-range"], TokenCollection.last.tags end - test "add duplicate tag to token_collection" do - create(:token_collection, name: "CKBNFT", cell_id: @cell.id, creator_id: @address.id, block_timestamp: 1.hour.ago.to_i, tags: ["rgbpp-compatible", "layer-1-asset"]) - new_tx = create(:ckb_transaction) - new_cell = create(:cell_output, address_id: @address.id, ckb_transaction_id: new_tx.id, tx_hash: new_tx.tx_hash) - create(:token_collection, name: "CKBNFT", cell_id: new_cell.id, creator_id: @address.id, block_timestamp: Time.now.to_i) + test "add rgb++ tag to token_collection" do + create(:token_collection, name: "CKBNFT", cell_id: @cell.id, creator_id: @address.id, block_timestamp: 1.hour.ago.to_i) TokenCollectionTagWorker.new.perform - assert_equal ["duplicate", "layer-1-asset"], TokenCollection.last.tags + assert_equal ["rgb++", "layer-1-asset"], TokenCollection.last.tags end end diff --git a/test/workers/xudt_tag_worker_test.rb b/test/workers/xudt_tag_worker_test.rb index f06bb5488..d590969ba 100644 --- a/test/workers/xudt_tag_worker_test.rb +++ b/test/workers/xudt_tag_worker_test.rb @@ -18,7 +18,7 @@ class XudtTagWorkerTest < ActiveJob::TestCase assert_changes -> { XudtTag.count }, from: 0, to: 1 do XudtTagWorker.new.perform end - assert_equal ["unnamed"], XudtTag.last.tags + assert_equal ["unnamed", "rgb++"], XudtTag.last.tags end test "insert to xudt_tags successfully" do @@ -28,7 +28,7 @@ class XudtTagWorkerTest < ActiveJob::TestCase assert_changes -> { XudtTag.count }, from: 1, to: 2 do XudtTagWorker.new.perform end - assert_equal ["rgbpp-compatible", "layer-1-asset", "supply-limited"], XudtTag.last.tags + assert_equal ["rgb++", "layer-1-asset", "supply-limited"], XudtTag.last.tags end test "insert invalid tag" do @@ -36,32 +36,40 @@ class XudtTagWorkerTest < ActiveJob::TestCase assert_changes -> { XudtTag.count }, from: 0, to: 1 do XudtTagWorker.new.perform end - assert_equal ["invalid"], XudtTag.last.tags + assert_equal ["invalid", "rgb++"], XudtTag.last.tags end test "insert suspicious tag" do - create(:udt, :xudt, symbol: "CK BB") + create(:udt, :xudt, symbol: "CK BB") assert_changes -> { XudtTag.count }, from: 0, to: 1 do XudtTagWorker.new.perform end - assert_equal ["suspicious"], XudtTag.last.tags + assert_equal ["suspicious", "rgb++"], XudtTag.last.tags end test "insert out-of-length-range tag" do - create(:udt, :xudt, symbol: "CKBBBB") + create(:udt, :xudt, symbol: "CK BBBB") + assert_changes -> { XudtTag.count }, from: 0, to: 1 do + XudtTagWorker.new.perform + end + assert_equal ["out-of-length-range", "rgb++"], XudtTag.last.tags + end + + test "insert utility tag" do + create(:udt, :xudt, symbol: "CKBBB", args: "0xdd6faefeffaa7d2a7b2e6890713c5fa4bbf378add1cfc1b27672a50a6ad3e83500000040") assert_changes -> { XudtTag.count }, from: 0, to: 1 do XudtTagWorker.new.perform end - assert_equal ["out-of-length-range"], XudtTag.last.tags + assert_equal ["utility", "rgb++"], XudtTag.last.tags end - test "insert duplicate tag" do + test "insert suspicious tag when not lp token but duplicate" do udt = create(:udt, :xudt, symbol: "CKBBB", block_timestamp: 1.day.ago.to_i * 1000) - create(:xudt_tag, udt_id: udt.id, udt_type_hash: udt.type_hash, tags: ["rgbpp-compatible", "layer-1-asset", "supply-limited"]) + create(:xudt_tag, udt_id: udt.id, udt_type_hash: udt.type_hash, tags: ["rgb++", "layer-1-asset", "supply-limited"]) create(:udt, :xudt, symbol: "ckbbb", block_timestamp: Time.now.to_i * 1000, issuer_address: @address.address_hash) assert_changes -> { XudtTag.count }, from: 1, to: 2 do XudtTagWorker.new.perform end - assert_equal ["duplicate", "layer-1-asset", "supply-limited"], XudtTag.last.tags + assert_equal ["suspicious", "rgb++"], XudtTag.last.tags end end From ac9ebccd5cc1a46f6de9f0589b8e566ecae0672a Mon Sep 17 00:00:00 2001 From: Rabbit Date: Fri, 2 Aug 2024 15:47:26 +0800 Subject: [PATCH 2/3] chore: refactor text sanitization in hex data parsing (#2117) --- app/utils/ckb_utils.rb | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/app/utils/ckb_utils.rb b/app/utils/ckb_utils.rb index 1bce9c67e..8941de0cc 100644 --- a/app/utils/ckb_utils.rb +++ b/app/utils/ckb_utils.rb @@ -614,27 +614,17 @@ def self.hexes_to_bins_sql(hex_strings) end def self.parse_spore_cluster_data(hex_data) - safe_encode = Proc.new do |str| - str.force_encoding("UTF-8").encode("UTF-8", invalid: :replace, undef: :replace, replace: "") - rescue Encoding::UndefinedConversionError, Encoding::InvalidByteSequenceError - "" - end + data = hex_data.slice(2..-1) + name_offset = [data.slice(8, 8)].pack("H*").unpack1("l") * 2 + description_offset = [data.slice(16, 8)].pack("H*").unpack1("l") * 2 + 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 - begin - data = hex_data.slice(2..-1) - name_offset = [data.slice(8, 8)].pack("H*").unpack1("l") * 2 - description_offset = [data.slice(16, 8)].pack("H*").unpack1("l") * 2 - 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 = safe_encode.call(name) - description = safe_encode.call(description) - - { name:, description: } - rescue StandardError => e - puts "Error parsing spore cluster data: #{e.message}" - { name: nil, description: nil } - end + { name: sanitize_string(name), description: sanitize_string(description) } + rescue StandardError => e + puts "Error parsing spore cluster data: #{e.message}" + { name: nil, description: nil } end def self.parse_spore_cell_data(hex_data) @@ -772,4 +762,10 @@ def self.parse_unique_cell(hex_data) symbol = [data.slice!(0, symbol_len * 2)].pack("H*") { decimal:, name: name.presence, symbol: symbol.presence } end + + def self.sanitize_string(str) + str.force_encoding("UTF-8").encode("UTF-8", invalid: :replace, undef: :replace, replace: "").gsub(/[[:cntrl:]\u2028\u2029\u200B]/, "") + rescue Encoding::UndefinedConversionError, Encoding::InvalidByteSequenceError + "" + end end From 7825000008544971f041d0949f201eb64b8d06f2 Mon Sep 17 00:00:00 2001 From: Rabbit Date: Mon, 5 Aug 2024 14:43:04 +0800 Subject: [PATCH 3/3] fix: optimize transactions sorting (#2120) --- app/interactions/addresses/ckb_transactions.rb | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/app/interactions/addresses/ckb_transactions.rb b/app/interactions/addresses/ckb_transactions.rb index 2b21ceba0..dcba4cfe6 100644 --- a/app/interactions/addresses/ckb_transactions.rb +++ b/app/interactions/addresses/ckb_transactions.rb @@ -4,7 +4,7 @@ class CkbTransactions < ActiveInteraction::Base object :request, class: ActionDispatch::Request string :key, default: nil - string :sort, default: "ckb_transaction_id.desc" + string :sort, default: "time.desc" integer :page, default: 1 integer :page_size, default: CkbTransaction.default_per_page @@ -29,16 +29,10 @@ def execute private def account_books_ordering - sort_by, sort_order = sort.split(".", 2) - sort_by = - case sort_by - when "time" then "ckb_transactions.block_timestamp" - else "ckb_transactions.id" - end + sort_by = "ckb_transactions.block_timestamp" + _, sort_order = sort.split(".", 2) - if sort_order.nil? || !sort_order.match?(/^(asc|desc)$/i) - sort_order = "asc" - end + sort_order = "asc" unless sort_order&.match?(/^(asc|desc)$/i) [sort_by, sort_order] end