Skip to content

Commit

Permalink
feat: address live cells contoller (#1610)
Browse files Browse the repository at this point in the history
Signed-off-by: Miles Zhang <[email protected]>
  • Loading branch information
zmcNotafraid authored Jan 30, 2024
1 parent 06d070d commit 15df613
Show file tree
Hide file tree
Showing 8 changed files with 249 additions and 26 deletions.
38 changes: 38 additions & 0 deletions app/controllers/api/v1/address_live_cells_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
module Api
module V1
class AddressLiveCellsController < ApplicationController
before_action :validate_pagination_params, :pagination_params

def show
address = Address.find_address!(params[:id])
raise Api::V1::Exceptions::AddressNotFoundError if address.is_a?(NullAddress)

order_by, asc_or_desc = live_cells_ordering
@addresses = address.cell_outputs.live.order(order_by => asc_or_desc).page(@page).per(@page_size).fast_page
options = FastJsonapi::PaginationMetaGenerator.new(
request:,
records: @addresses,
page: @page,
page_size: @page_size,
).call
render json: CellOutputSerializer.new(@addresses, options).serialized_json
end

private

def pagination_params
@page = params[:page] || 1
@page_size = params[:page_size] || CellOutput.default_per_page
end

def live_cells_ordering
sort, order = params.fetch(:sort, "block_timestamp.desc").split(".", 2)
if order.nil? || !order.match?(/^(asc|desc)$/i)
order = "asc"
end

[sort, order]
end
end
end
end
35 changes: 34 additions & 1 deletion app/models/cell_output.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ class CellOutput < ApplicationRecord
SYSTEM_TX_HASH = "0x0000000000000000000000000000000000000000000000000000000000000000".freeze
MAXIMUM_DOWNLOADABLE_SIZE = 64000
MIN_SUDT_AMOUNT_BYTESIZE = 16
MAX_PAGINATES_PER = 100
DEFAULT_PAGINATES_PER = 10
paginates_per DEFAULT_PAGINATES_PER
max_paginates_per MAX_PAGINATES_PER

enum status: { live: 0, dead: 1, pending: 2, rejected: 3 }
enum cell_type: {
normal: 0,
Expand All @@ -19,7 +24,7 @@ class CellOutput < ApplicationRecord
spore_cell: 12,
omiga_inscription_info: 13,
omiga_inscription: 14,
xudt: 15
xudt: 15,
}

belongs_to :ckb_transaction
Expand Down Expand Up @@ -267,6 +272,34 @@ def nrc_721_nft_info
CkbUtils.hash_value_to_s(value)
end

def omiga_inscription_info
return unless cell_type.in?(%w(omiga_inscription_info omiga_inscription))

case cell_type
when "omiga_inscription_info"
info = OmigaInscriptionInfo.find_by(code_hash: type_script.code_hash,
hash_type: type_script.hash_type,
args: type_script.args)
value = {
symbol: info.symbol,
name: info.name,
decimal: info.decimal,
amount: 0,
}
when "omiga_inscription"
udt = Udt.find_by(type_hash:)
value = {
symbol: udt.symbol,
name: udt.name,
decimal: udt.decimal,
amount: udt_amount,
}
else
raise "invalid cell type"
end
CkbUtils.hash_value_to_s(value)
end

def create_token
case cell_type
when "m_nft_class"
Expand Down
30 changes: 19 additions & 11 deletions app/models/concerns/display_cells.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ def cellbase_display_inputs
occupied_capacity: nil,
address_hash: nil,
target_block_number: cellbase.target_block_number,
generated_tx_hash: tx_hash
)
generated_tx_hash: tx_hash,
),
]
end

Expand All @@ -55,7 +55,7 @@ def cellbase_display_outputs
proposal_reward: cellbase.proposal_reward,
secondary_reward: cellbase.secondary_reward,
status: output.status,
consumed_tx_hash: consumed_tx_hash
consumed_tx_hash:,
)
end
end
Expand All @@ -73,8 +73,8 @@ def normal_tx_display_inputs(cell_inputs_for_display)
cell_index: cell_input.previous_index,
since: {
raw: hex_since(cell_input.since.to_i),
median_timestamp: cell_input.block&.median_timestamp.to_i
}
median_timestamp: cell_input.block&.median_timestamp.to_i,
},
})
end

Expand All @@ -89,8 +89,8 @@ def normal_tx_display_inputs(cell_inputs_for_display)
cell_type: previous_cell_output.cell_type,
since: {
raw: hex_since(cell_input.since.to_i),
median_timestamp: cell_input.block&.median_timestamp.to_i
}
median_timestamp: cell_input.block&.median_timestamp.to_i,
},
}

if previous_cell_output.nervos_dao_withdrawing?
Expand Down Expand Up @@ -122,8 +122,8 @@ def normal_tx_display_outputs(cell_outputs_for_display)
occupied_capacity: output.occupied_capacity,
address_hash: output.address_hash,
status: output.status,
consumed_tx_hash: consumed_tx_hash,
cell_type: output.cell_type
consumed_tx_hash:,
cell_type: output.cell_type,
}

display_output.merge!(attributes_for_udt_cell(output)) if output.udt?
Expand All @@ -135,6 +135,9 @@ def normal_tx_display_outputs(cell_outputs_for_display)
if output.cell_type.in?(%w(nrc_721_token nrc_721_factory))
display_output.merge!(attributes_for_nrc_721_cell(output))
end
if output.cell_type.in?(%w(omiga_inscription_info omiga_inscription))
display_output.merge!(attributes_for_omiga_inscription_cell(output))
end

CkbUtils.hash_value_to_s(display_output)
end
Expand Down Expand Up @@ -165,6 +168,11 @@ def attributes_for_nrc_721_cell(nrc_721_cell)
{ nrc_721_token_info: info, extra_info: info }
end

def attributes_for_omiga_inscription_cell(omiga_inscription_cell)
info = omiga_inscription_cell.omiga_inscription_info
{ omiga_inscription_info: info, extra_info: info }
end

def attributes_for_dao_input(nervos_dao_withdrawing_cell, is_phase2 = true)
nervos_dao_withdrawing_cell_generated_tx = nervos_dao_withdrawing_cell.ckb_transaction
nervos_dao_deposit_cell = nervos_dao_withdrawing_cell_generated_tx.
Expand All @@ -181,7 +189,7 @@ def attributes_for_dao_input(nervos_dao_withdrawing_cell, is_phase2 = true)
compensation_started_timestamp: compensation_started_block.timestamp,
compensation_ended_block_number: compensation_ended_block.number,
compensation_ended_timestamp: compensation_ended_block.timestamp,
interest: interest
interest:,
}

if is_phase2
Expand All @@ -194,7 +202,7 @@ def attributes_for_dao_input(nervos_dao_withdrawing_cell, is_phase2 = true)
end

def 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
end
end
42 changes: 42 additions & 0 deletions app/serializers/cell_output_serializer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
class CellOutputSerializer
include FastJsonapi::ObjectSerializer

attributes :cell_type, :tx_hash, :cell_index, :type_hash, :data

attribute :capacity do |object|
object.capacity.to_s
end

attribute :occupied_capacity do |object|
object.occupied_capacity.to_s
end

attribute :block_timestamp do |object|
object.block_timestamp.to_s
end

attribute :type_script do |object|
object&.type_script&.to_node
end

attribute :lock_script do |object|
object.lock_script.to_node
end

attribute :extra_info do |object|
case object.cell_type
when "udt"
object.udt_info
when "cota_registry"
object.cota_registry_info
when "cota_regular"
object.cota_regular_info
when "m_nft_issuer", "m_nft_class", "m_nft_token"
object.m_nft_info
when "nrc_721_token", "nrc_721_factory"
object.nrc_721_nft_info
when "omiga_inscription_info", "omiga_inscription"
object.omiga_inscription_info
end
end
end
1 change: 1 addition & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
resources :monetary_data, only: :show
resources :udt_verifications, only: :update
resources :address_pending_transactions, only: :show
resources :address_live_cells, only: :show
end
end
draw "v2"
Expand Down
23 changes: 12 additions & 11 deletions test/controllers/api/v1/address_dao_transactions_controller_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ class AddressDaoTransactionsControllerTest < ActionDispatch::IntegrationTest

valid_get api_v1_address_dao_transaction_url(address.address_hash)

options = FastJsonapi::PaginationMetaGenerator.new(request: request, records: ckb_dao_transactions, page: page, page_size: page_size).call
options = FastJsonapi::PaginationMetaGenerator.new(request:, records: ckb_dao_transactions, page:, page_size:).call

assert_equal CkbTransactionsSerializer.new(ckb_dao_transactions, options.merge(params: { previews: true })).serialized_json, response.body
end
Expand All @@ -76,7 +76,7 @@ class AddressDaoTransactionsControllerTest < ActionDispatch::IntegrationTest

valid_get api_v1_address_dao_transaction_url(address.lock_hash)

options = FastJsonapi::PaginationMetaGenerator.new(request: request, records: ckb_dao_transactions, page: page, page_size: page_size).call
options = FastJsonapi::PaginationMetaGenerator.new(request:, records: ckb_dao_transactions, page:, page_size:).call

assert_equal CkbTransactionsSerializer.new(ckb_dao_transactions, options.merge(params: { previews: true })).serialized_json, response.body
end
Expand All @@ -89,7 +89,8 @@ class AddressDaoTransactionsControllerTest < ActionDispatch::IntegrationTest

response_tx_transaction = json["data"].first

assert_equal %w(block_number block_timestamp display_inputs display_inputs_count display_outputs display_outputs_count income is_cellbase transaction_hash created_at create_timestamp).sort, response_tx_transaction["attributes"].keys.sort
assert_equal %w(block_number block_timestamp display_inputs display_inputs_count display_outputs display_outputs_count income is_cellbase transaction_hash created_at create_timestamp).sort,
response_tx_transaction["attributes"].keys.sort
end

test "should return error object when no records found by id" do
Expand Down Expand Up @@ -149,9 +150,9 @@ class AddressDaoTransactionsControllerTest < ActionDispatch::IntegrationTest
fake_dao_deposit_transaction(30, address)
address_dao_transactions = address.ckb_dao_transactions.recent.page(page).per(page_size)

valid_get api_v1_address_dao_transaction_url(address.address_hash), params: { page: page }
valid_get api_v1_address_dao_transaction_url(address.address_hash), params: { page: }
records_counter = RecordCounters::AddressDaoTransactions.new(address)
options = FastJsonapi::PaginationMetaGenerator.new(request: request, records: address_dao_transactions, page: page, page_size: page_size, records_counter: records_counter).call
options = FastJsonapi::PaginationMetaGenerator.new(request:, records: address_dao_transactions, page:, page_size:, records_counter:).call
response_transaction = CkbTransactionsSerializer.new(address_dao_transactions, options.merge(params: { previews: true })).serialized_json

assert_equal response_transaction, response.body
Expand All @@ -165,10 +166,10 @@ class AddressDaoTransactionsControllerTest < ActionDispatch::IntegrationTest
fake_dao_deposit_transaction(15, address)
address_dao_transactions = address.ckb_dao_transactions.recent.page(page).per(page_size)

valid_get api_v1_address_dao_transaction_url(address.address_hash), params: { page_size: page_size }
valid_get api_v1_address_dao_transaction_url(address.address_hash), params: { page_size: }

records_counter = RecordCounters::AddressDaoTransactions.new(address)
options = FastJsonapi::PaginationMetaGenerator.new(request: request, records: address_dao_transactions, page: page, page_size: page_size, records_counter: records_counter).call
options = FastJsonapi::PaginationMetaGenerator.new(request:, records: address_dao_transactions, page:, page_size:, records_counter:).call
response_transaction = CkbTransactionsSerializer.new(address_dao_transactions, options.merge(params: { previews: true })).serialized_json

assert_equal response_transaction, response.body
Expand All @@ -182,10 +183,10 @@ class AddressDaoTransactionsControllerTest < ActionDispatch::IntegrationTest
fake_dao_deposit_transaction(30, address)
address_dao_transactions = address.ckb_dao_transactions.recent.page(page).per(page_size)

valid_get api_v1_address_dao_transaction_url(address.address_hash), params: { page: page, page_size: page_size }
valid_get api_v1_address_dao_transaction_url(address.address_hash), params: { page:, page_size: }

records_counter = RecordCounters::AddressDaoTransactions.new(address)
options = FastJsonapi::PaginationMetaGenerator.new(request: request, records: address_dao_transactions, page: page, page_size: page_size, records_counter: records_counter).call
options = FastJsonapi::PaginationMetaGenerator.new(request:, records: address_dao_transactions, page:, page_size:, records_counter:).call
response_transaction = CkbTransactionsSerializer.new(address_dao_transactions, options.merge(params: { previews: true })).serialized_json

assert_equal response_transaction, response.body
Expand All @@ -198,10 +199,10 @@ class AddressDaoTransactionsControllerTest < ActionDispatch::IntegrationTest
fake_dao_deposit_transaction(3, address)
address_dao_transactions = address.ckb_dao_transactions.recent.page(page).per(page_size)

valid_get api_v1_address_dao_transaction_url(address.address_hash), params: { page: page, page_size: page_size }
valid_get api_v1_address_dao_transaction_url(address.address_hash), params: { page:, page_size: }

records_counter = RecordCounters::AddressDaoTransactions.new(address)
options = FastJsonapi::PaginationMetaGenerator.new(request: request, records: address_dao_transactions, page: page, page_size: page_size, records_counter: records_counter).call
options = FastJsonapi::PaginationMetaGenerator.new(request:, records: address_dao_transactions, page:, page_size:, records_counter:).call
response_transaction = CkbTransactionsSerializer.new(address_dao_transactions, options.merge(params: { previews: true })).serialized_json

assert_equal [], json["data"]
Expand Down
Loading

0 comments on commit 15df613

Please sign in to comment.