Skip to content

Commit

Permalink
Feat/rgb (#1682)
Browse files Browse the repository at this point in the history
* refactor: search live cells with bitcoin address

* refactor: get address info with bitcoin address

* chore: adjust test
  • Loading branch information
rabbitz authored Mar 18, 2024
1 parent 993a28b commit c066018
Show file tree
Hide file tree
Showing 11 changed files with 138 additions and 111 deletions.
38 changes: 8 additions & 30 deletions app/controllers/api/v1/address_live_cells_controller.rb
Original file line number Diff line number Diff line change
@@ -1,39 +1,17 @@
module Api
module V1
class AddressLiveCellsController < ApplicationController
before_action :validate_pagination_params, :pagination_params
before_action :validate_pagination_params

def show
expires_in 1.minutes, public: true, must_revalidate: true, stale_while_revalidate: 10.seconds
expires_in 1.minute, public: true, must_revalidate: true, stale_while_revalidate: 10.seconds

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]
json = Addresses::LiveCells.run!(
{ request:,
key: params[:id], sort: params[:sort],
page: params[:page], page_size: params[:page_size] },
)
render json:
end
end
end
Expand Down
1 change: 1 addition & 0 deletions app/controllers/api/v1/address_transactions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ class AddressTransactionsController < ApplicationController

def show
expires_in 10.seconds, public: true, must_revalidate: true, stale_while_revalidate: 5.seconds

json = Addresses::CkbTransactions.run!(
{ request:,
key: params[:id], sort: params[:sort],
Expand Down
32 changes: 6 additions & 26 deletions app/controllers/api/v1/addresses_controller.rb
Original file line number Diff line number Diff line change
@@ -1,34 +1,14 @@
module Api
module V1
class AddressesController < ApplicationController
before_action :validate_query_params

def show
address = Address.find_address!(params[:id])

render json: json_response(address)
end

private

def validate_query_params
validator = Validations::Address.new(params)

if validator.invalid?
errors = validator.error_object[:errors]
status = validator.error_object[:status]

render json: errors, status:
end
end
expires_in 1.minute, public: true, must_revalidate: true, stale_while_revalidate: 10.seconds

def json_response(address)
if QueryKeyUtils.valid_hex?(params[:id])
LockHashSerializer.new(address)
else
presented_address = address.is_a?(NullAddress) ? NullAddress.new(params[:id]) : address
AddressSerializer.new(presented_address)
end
json = Addresses::Info.run!(
{ request:, key: params[:id],
page: params[:page], page_size: params[:page_size] },
)
render json:
end
end
end
Expand Down
22 changes: 22 additions & 0 deletions app/interactions/addresses/info.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
module Addresses
class Info < ActiveInteraction::Base
include Api::V1::Exceptions

object :request, class: ActionDispatch::Request
string :key, default: nil
integer :page, default: 1
integer :page_size, default: Address.default_per_page

def execute
address = Explore.run!(key:)
raise AddressNotFoundError if address.is_a?(NullAddress)

return LockHashSerializer.new(address[0]) if QueryKeyUtils.valid_hex?(key)

options = FastJsonapi::PaginationMetaGenerator.new(
request:, records: address, page:, page_size:, total_count: address.count,
).call
AddressSerializer.new(address, options)
end
end
end
37 changes: 37 additions & 0 deletions app/interactions/addresses/live_cells.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
module Addresses
class LiveCells < ActiveInteraction::Base
include Api::V1::Exceptions

object :request, class: ActionDispatch::Request
string :key, default: nil
string :sort, default: "block_timestamp.desc"
integer :page, default: 1
integer :page_size, default: CellOutput.default_per_page

def execute
address = Explore.run!(key:)
raise AddressNotFoundError if address.is_a?(NullAddress)

order_by, asc_or_desc = live_cells_ordering
records = CellOutput.live.where(address_id: address.map(&:id)).
order(order_by => asc_or_desc).
page(page).per(page_size).fast_page
options = FastJsonapi::PaginationMetaGenerator.new(
request:, records:, page:, page_size:,
).call

CellOutputSerializer.new(records, options).serialized_json
end

private

def live_cells_ordering
sort_by, sort_order = sort.split(".", 2)
if sort_order.nil? || !sort_order.match?(/^(asc|desc)$/i)
sort_order = "asc"
end

[sort_by, sort_order]
end
end
end
48 changes: 20 additions & 28 deletions app/interactions/addresses/pending_transactions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,24 @@ def execute
address = Explore.run!(key:)
raise AddressNotFoundError if address.is_a?(NullAddress)

address_id = address.map(&:id)

order_by, asc_or_desc = account_books_ordering
account_books =
AccountBook.joins(:ckb_transaction).
where(account_books: { address_id: },
ckb_transactions: { tx_status: "pending" }).
order(order_by => asc_or_desc).
page(page).per(page_size).fast_page

ckb_transaction_ids = account_books.map(&:ckb_transaction_id)
ckb_transaction_ids = CellInput.where(ckb_transaction_id: ckb_transaction_ids).
where.not(previous_cell_output_id: nil, from_cell_base: false).
distinct.pluck(:ckb_transaction_id)
records = CkbTransaction.where(id: ckb_transaction_ids).
select(select_fields).
order(order_by => asc_or_desc)
AccountBook.joins(:ckb_transaction).where(
account_books: { address_id: address.map(&:id) },
ckb_transactions: { tx_status: "pending" },
)
ckb_transaction_ids =
CellInput.where(ckb_transaction_id: account_books.map(&:ckb_transaction_id)).
where.not(previous_cell_output_id: nil, from_cell_base: false).
distinct.pluck(:ckb_transaction_id)
records =
CkbTransaction.where(id: ckb_transaction_ids).
select(select_fields).
order(transactions_ordering).
page(page).per(page_size)

options = paginate_options(records, address_id)
options = FastJsonapi::PaginationMetaGenerator.new(
request:, records:, page:, page_size:,
).call
options.merge!(params: { previews: true, address: })

result = CkbTransactionsSerializer.new(records, options)
Expand All @@ -39,26 +38,19 @@ def execute

private

def account_books_ordering
def transactions_ordering
sort_by, sort_order = sort.split(".", 2)
sort_by =
case sort_by
when "time" then "ckb_transactions.block_timestamp"
else "ckb_transactions.id"
when "time" then "block_timestamp"
else "id"
end

if sort_order.nil? || !sort_order.match?(/^(asc|desc)$/i)
sort_order = "asc"
end

[sort_by, sort_order]
end

def paginate_options(records, address_id)
total_count = AccountBook.where(address_id:).count
FastJsonapi::PaginationMetaGenerator.new(
request:, records:, page:, page_size:, total_count:,
).call
"#{sort_by} #{sort_order} NULLS LAST"
end

def select_fields
Expand Down
6 changes: 5 additions & 1 deletion app/models/address.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
class Address < ApplicationRecord
PREFIX_MAINNET = "ckb".freeze
PREFIX_TESTNET = "ckt".freeze
MAX_PAGINATES_PER = 1000
DEFAULT_PAGINATES_PER = 100
paginates_per DEFAULT_PAGINATES_PER
max_paginates_per MAX_PAGINATES_PER

has_many :cell_outputs, dependent: :destroy
has_many :account_books, dependent: :destroy
Expand All @@ -9,7 +13,7 @@ class Address < ApplicationRecord
has_many :udt_accounts
has_many :dao_events

has_one :bitcoin_address_mapping
has_one :bitcoin_address_mapping, foreign_key: "ckb_address_id"
has_one :bitcoin_address, through: :bitcoin_address_mapping

validates :balance, :cell_consumed, :ckb_transactions_count, :interest, :dao_deposit,
Expand Down
4 changes: 4 additions & 0 deletions app/models/null_address.rb
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ def balance_occupied
0
end

def bitcoin_address
nil
end

alias_method :cached_lock_script, :lock_script
alias_method :query_address, :address_hash
end
3 changes: 3 additions & 0 deletions app/serializers/address_serializer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -131,4 +131,7 @@ class AddressSerializer
attribute :balance_occupied do |object|
object.balance_occupied.to_s
end
attribute :bitcoin_address_hash do |object|
object.bitcoin_address&.address_hash
end
end
Loading

0 comments on commit c066018

Please sign in to comment.