Skip to content

Commit

Permalink
Merge pull request #1722 from nervosnetwork/develop
Browse files Browse the repository at this point in the history
Deploy to testnet
  • Loading branch information
zmcNotafraid committed Apr 2, 2024
2 parents cc91460 + 3cb5100 commit 5598f68
Show file tree
Hide file tree
Showing 15 changed files with 255 additions and 10 deletions.
78 changes: 78 additions & 0 deletions app/controllers/api/v1/xudts_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
module Api
module V1
class XudtsController < ApplicationController
before_action :validate_query_params, only: :show
before_action :validate_pagination_params, :pagination_params, only: :index

def index
udts = Udt.xudt

if stale?(udts)
expires_in 30.minutes, public: true, stale_while_revalidate: 10.minutes, stale_if_error: 10.minutes

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], published: true)
render json: UdtSerializer.new(udt)
rescue ActiveRecord::RecordNotFound
raise Api::V1::Exceptions::UdtNotFoundError
end

def download_csv
args = params.permit(:id, :start_date, :end_date, :start_number, :end_number, udt: {})
file = CsvExportable::ExportUdtTransactionsJob.perform_now(args.to_h)

send_data file, type: "text/csv; charset=utf-8; header=present",
disposition: "attachment;filename=xudt_transactions.csv"
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
2 changes: 1 addition & 1 deletion app/models/cell_input.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class CellInput < ApplicationRecord
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, omiga_inscription_info: 13, omiga_inscription: 14,
xudt: 15
xudt: 15, unique_cell: 16
}

def output
Expand Down
1 change: 1 addition & 0 deletions app/models/cell_output.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class CellOutput < ApplicationRecord
omiga_inscription_info: 13,
omiga_inscription: 14,
xudt: 15,
unique_cell: 16,
}

belongs_to :ckb_transaction
Expand Down
4 changes: 4 additions & 0 deletions app/models/ckb_sync/api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ def xudt_code_hash
Settings.xudt_code_hash
end

def unique_cell_code_hash
Settings.unique_cell_code_hash
end

def rgbpp_code_hash
Settings.rgbpp_code_hash
end
Expand Down
39 changes: 35 additions & 4 deletions app/models/ckb_sync/new_node_data_processor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,9 @@ def update_udt_info(local_block)
local_block.cell_outputs.omiga_inscription.select(:id, :type_hash).each do |udt_output|
type_hashes << udt_output.type_hash
end
local_block.cell_outputs.xudt.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|
type_hashes << udt_output.type_hash
Expand Down Expand Up @@ -454,7 +457,7 @@ def update_or_create_udt_accounts!(local_block)
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))
spore_cell omiga_inscription xudt))

address = Address.find(udt_output.address_id)
udt_type = udt_type(udt_output.cell_type)
Expand Down Expand Up @@ -485,7 +488,7 @@ def update_or_create_udt_accounts!(local_block)
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))
spore_cell omiga_inscription xudt))

address = Address.find(udt_output.address_id)
udt_type = udt_type(udt_output.cell_type)
Expand All @@ -496,7 +499,7 @@ def update_or_create_udt_accounts!(local_block)
:symbol, :decimal, :published, :code_hash, :type_hash, :created_at).take!
if udt_account.present?
case udt_type
when "sudt", "omiga_inscription"
when "sudt", "omiga_inscription", "xudt"
udt_accounts_attributes << { id: udt_account.id, amount:,
created_at: udt.created_at }
when "m_nft_token"
Expand Down Expand Up @@ -531,6 +534,8 @@ def udt_account_amount(udt_type, type_hash, address)
case udt_type
when "sudt"
address.cell_outputs.live.udt.where(type_hash:).sum(:udt_amount)
when "xudt"
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"
Expand Down Expand Up @@ -631,7 +636,7 @@ def build_udts!(local_block, outputs, outputs_data)
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
omiga_inscription_info omiga_inscription))
omiga_inscription_info omiga_inscription xudt))

type_hash, parsed_udt_type =
if cell_type == "omiga_inscription_info"
Expand Down Expand Up @@ -716,6 +721,17 @@ def build_udts!(local_block, outputs, outputs_data)
nft_token_attr[:decimal] = info[:decimal]
nft_token_attr[:published] = true
end
if cell_type == "xudt"
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])
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
end
end
# fill issuer_address after publish the token
udts_attributes << {
type_hash:, udt_type: parsed_udt_type, block_timestamp: local_block.timestamp, args: output.type.args,
Expand Down Expand Up @@ -1055,6 +1071,12 @@ def build_cell_inputs(
udt_address_ids[tx_index] << address_id
contained_udt_ids[tx_index] << Udt.where(type_hash:,
udt_type: "omiga_inscription").pick(:id)
when "xudt"
tags[tx_index] << "xudt"
udt_address_ids[tx_index] << address_id
contained_udt_ids[tx_index] << Udt.where(type_hash:,
udt_type: "xudt").pick(:id)

when "nrc_721_token"
tags[tx_index] << "nrc_721_token"
udt_address_ids[tx_index] << address_id
Expand Down Expand Up @@ -1121,6 +1143,13 @@ def build_cell_outputs!(
contained_udt_ids[tx_index] << Udt.where(
type_hash: item.type.compute_hash, udt_type: "omiga_inscription",
).pick(:id)
elsif attr[:cell_type] == "xudt"
tags[tx_index] << "xudt"
udt_address_ids[tx_index] << address_id
contained_udt_ids[tx_index] << Udt.where(
type_hash: item.type.compute_hash, udt_type: "xudt",
).pick(:id)

elsif attr[:cell_type].in?(%w(m_nft_token nrc_721_token spore_cell))
token_transfer_ckb_tx_ids << ckb_txs[tx_index]["id"]
end
Expand Down Expand Up @@ -1185,6 +1214,8 @@ def udt_amount(cell_type, output_data, type_script_args)
case cell_type
when "udt"
CkbUtils.parse_udt_cell_data(output_data)
when "xudt"
CkbUtils.parse_udt_cell_data(output_data)
when "omiga_inscription"
CkbUtils.parse_omiga_inscription_data(output_data)[:mint_limit]
when "m_nft_token"
Expand Down
2 changes: 1 addition & 1 deletion app/models/udt.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ class Udt < ApplicationRecord
has_one :omiga_inscription_info

enum udt_type: { sudt: 0, m_nft_token: 1, nrc_721_token: 2, spore_cell: 3,
omiga_inscription: 4 }
omiga_inscription: 4, xudt: 5 }

validates_presence_of :total_amount
validates :decimal,
Expand Down
17 changes: 15 additions & 2 deletions app/utils/ckb_utils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -406,15 +406,16 @@ def self.cell_type(type_script, output_data)
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.omiga_inscription_info_code_hash,
CkbSync::Api.instance.xudt_code_hash
CkbSync::Api.instance.xudt_code_hash, CkbSync::Api.instance.unique_cell_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_hashes,
*CkbSync::Api.instance.spore_cell_code_hashes,
].include?(type_script&.code_hash) && type_script&.hash_type == "data1" ||
CkbSync::Api.instance.mode == CKB::MODE::MAINNET && [CkbSync::Api.instance.xudt_code_hash].include?(type_script&.code_hash) && type_script&.hash_type == "data1"
CkbSync::Api.instance.mode == CKB::MODE::MAINNET && [CkbSync::Api.instance.xudt_code_hash,
CkbSync::Api.instance.unique_cell_code_hash].include?(type_script&.code_hash) && type_script&.hash_type == "data1"

case type_script&.code_hash
when Settings.dao_code_hash, Settings.dao_type_hash
Expand Down Expand Up @@ -453,6 +454,8 @@ def self.cell_type(type_script, output_data)
"xudt"
end
end
when Settings.unique_cell_code_hash
"unique_cell"
else
if is_nrc_721_token_cell?(output_data)
"nrc_721_token"
Expand Down Expand Up @@ -658,4 +661,14 @@ def self.parse_rgbpp_args(args)

[txid, out_index]
end

def self.parse_unique_cell(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*")
{ decimal:, name: name.presence, symbol: symbol.presence }
end
end
5 changes: 5 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@
get :download_csv
end
end
resources :xudts, only: %i(index show) do
collection do
get :download_csv
end
end
resources :omiga_inscriptions, only: %i(index show) do
collection do
get :download_csv
Expand Down
4 changes: 3 additions & 1 deletion config/settings.mainnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ omiga_inscription_code_hash: "0x7490970e6af9b9fe63fc19fc523a12b2ec69027e6ae484ed
# xudt
xudt_code_hash: "0x50bd8d6680b8b9cf98b73f3c08faf8b2a21914311954118ad6609be6e78a1b95"

unique_cell_code_hash: "0xcc2518c2c1384f2473c96f63c4e74074984296f358512ee7f54c848d4c135040"

# 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"
Expand All @@ -52,7 +54,7 @@ secp_multisig_cell_type_hash: "0x5c5069eb0857efc65e1bca0c07df34c31663b3622fd3876
dao_code_hash: "0x516be0333273bbe12a723f3be583c524f0b6089326f89c49fc61e24d1f56be21"
dao_type_hash: "0x82d76d1b75fe2fd9a27dfbaa65a039221a380d76c926f378d3f81cf3e7e13f2e"
sudt_cell_type_hash: "0x5e7a36a77e68eecc013dfa2fe6a23f3b6c344b04005808694ae6dd45eea4cfd5"
sudt1_cell_type_hash: ''
sudt1_cell_type_hash: ""

# epoch reward
default_epoch_reward: "1_917_808_21917808"
Expand Down
3 changes: 2 additions & 1 deletion config/settings.testnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ omiga_inscription_info_code_hash: "0x50fdea2d0030a8d0b3d69f883b471cab2a29cae6f01
omiga_inscription_code_hash: "0x3a241ceceede72a5f55c8fb985652690f09a517d6c9070f0df0d3572fa03fb70"
# xudt
xudt_code_hash: "0x25c29dc317811a6f6f3985a7a9ebc4838bd388d19d0feeecf0bcd60f6c0975bb"
unique_cell_code_hash: "0x8e341bcfec6393dcd41e635733ff2dca00a6af546949f70c57a706c0f344df8b"

# 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)
Expand All @@ -53,7 +54,7 @@ secp_multisig_cell_type_hash: "0x5c5069eb0857efc65e1bca0c07df34c31663b3622fd3876
dao_code_hash: "0x516be0333273bbe12a723f3be583c524f0b6089326f89c49fc61e24d1f56be21"
dao_type_hash: "0x82d76d1b75fe2fd9a27dfbaa65a039221a380d76c926f378d3f81cf3e7e13f2e"
sudt_cell_type_hash: "0x48dbf59b4c7ee1547238021b4869bceedf4eea6b43772e5d66ef8865b6ae7212"
sudt1_cell_type_hash: '0xc5e5dcf215925f7ef4dfaf5f4b4f105bc321c02776d6e7d52a1db3fcd9d011a4'
sudt1_cell_type_hash: "0xc5e5dcf215925f7ef4dfaf5f4b4f105bc321c02776d6e7d52a1db3fcd9d011a4"

# epoch reward
default_epoch_reward: "1_917_808_21917808"
Expand Down
23 changes: 23 additions & 0 deletions test/controllers/api/v1/xudts_controller_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
require "test_helper"

module Api
module V1
class XudtsControllerTest < ActionDispatch::IntegrationTest
test "should get success code when call show" do
udt = create(:udt, :xudt, published: true)

valid_get api_v1_xudt_url(udt.type_hash)

assert_response :success
end

test "should get success code when call index" do
create(:udt, :xudt, published: true)

valid_get api_v1_xudts_url

assert_response :success
end
end
end
end
6 changes: 6 additions & 0 deletions test/factories/udt.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,5 +55,11 @@
udt_id: udt.id)
end
end

trait :xudt do
udt_type { "xudt" }
symbol { "Unique BBQ" }
decimal { 8 }
end
end
end
33 changes: 33 additions & 0 deletions test/models/ckb_sync/node_data_processor_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4152,6 +4152,39 @@ class NodeDataProcessorTest < ActiveSupport::TestCase
end
end

test "create xudt with unique cell" do
CkbSync::Api.any_instance.stubs(:mode).returns("testnet")
CkbSync::Api.any_instance.stubs(:xudt_code_hash).returns("0x25c29dc317811a6f6f3985a7a9ebc4838bd388d19d0feeecf0bcd60f6c0975bb")
CkbSync::Api.any_instance.stubs(:unique_cell_code_hash).returns("0x8e341bcfec6393dcd41e635733ff2dca00a6af546949f70c57a706c0f344df8b")

VCR.use_cassette("blocks/34") do
node_block = CkbSync::Api.instance.get_block_by_number(34)
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: 0,
address: input_address1,
cell_type: "normal",
lock_script_id: address1_lock.id,
type_script_id: nil)
node_data_processor.process_block(node_block)
xudt = Udt.first
assert_equal 1, Udt.count
assert_equal "Unique BBQ", xudt.full_name
assert_equal 8, xudt.decimal
assert_equal "xudt", xudt.udt_type
end
end

private

def node_data_processor
Expand Down
Loading

0 comments on commit 5598f68

Please sign in to comment.