Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deploy to testnet #1385

Merged
merged 8 commits into from
Aug 21, 2023
Merged
23 changes: 22 additions & 1 deletion app/controllers/api/v1/udts_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,30 @@ def index
end
end

def show
def update
udt = Udt.find_by!(type_hash: params[:id], published: true)
attrs = {
symbol: params[:symbol],
full_name: params[:full_name],
decimal: params[:decimal],
total_amount: params[:total_amount],
description: params[:description],
operator_website: params[:operator_website],
icon_file: params[:icon_file],
uan: params[:uan],
display_name: params[:display_name],
contact_info: params[:contact_info]
}
udt.update!(attrs)
render json: :ok
rescue ActiveRecord::RecordNotFound
raise Api::V1::Exceptions::UdtNotFoundError
rescue ActiveRecord::RecordInvalid => e
raise Api::V1::Exceptions::UdtInfoInvalidError.new(e)
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
Expand Down
161 changes: 76 additions & 85 deletions app/controllers/api/v2/ckb_transactions_controller.rb
Original file line number Diff line number Diff line change
@@ -1,103 +1,94 @@
module Api
module V2
class CkbTransactionsController < ApplicationController
before_action :find_transaction, only: :details
before_action :set_page_and_page_size, only: :details

class CkbTransactionsController < BaseController
# transaction lite info
def details
capacities = {}
@ckb_transaction.display_inputs.select{ |e| e[:cell_type] == 'normal' }.each {|input|
capacities[input[:address_hash]] ||= 0
capacities[input[:address_hash]] -= input[:capacity].to_d
}
ckb_transaction = CkbTransaction.where(tx_hash: params[:id]).order(tx_status: :desc).first
head :not_found and return if ckb_transaction.blank?

@ckb_transaction.display_outputs.select{ |e| e[:cell_type] == 'normal' }.each {|output|
capacities[output[:address_hash]] ||= 0
capacities[output[:address_hash]] += output[:capacity].to_d
}
json = capacities.map { |address, value|
{
address: address,
transfers: [
{
asset: "CKB",
capacity: value,
token_name: "CKB",
entity_type: "CKB",
transfer_type: "ordinary_transfer"
}
]
}
}
expires_in 10.seconds, public: true, must_revalidate: true

input_capacities = build_cell_capacities(ckb_transaction.display_inputs)
output_capacities = build_cell_capacities(ckb_transaction.display_outputs)
transfers = build_transfers(input_capacities, output_capacities)

render json: {data: json}
render json: { data: transfers }
end

private
def find_transaction
@ckb_transaction = CkbTransaction.find_by(tx_hash: params[:id])
end

def set_page_and_page_size
@page = params[:page] || 1
@page_size = params[:page_size] || 10
end
def build_cell_capacities(outputs)
cell_capacities = Hash.new { |hash, key| hash[key] = {} }
outputs.each do |output|
parsed_output = JSON.parse(output.to_json, object_class: OpenStruct)
next if parsed_output.from_cellbase

def get_transaction_content address_ids, cell_outputs
transaction_data = []
transfers = []
address_ids.each do |address_id|
cell_outputs.where(address_id: address_id.address_id).each do |cell_output|
entity_type = "CKB"
transfer_type = "ordinary_transfer"
if cell_output.nervos_dao_deposit?
transfer_type = "nervos_dao_deposit"
elsif cell_output.nervos_dao_withdrawing?
transfer_type = "nervos_dao_withdrawing"
interest_data = get_nervos_dao_withdrawing_data(cell_output)
transfer.merge(interest_data)
elsif cell_output.cell_type.in?(%w(nrc_721_token nrc_721_factory))
entity_type = "nft"
transfer_type = "nft_transfer"
elsif cell_output.cell_type.in?(%w(m_nft_issuer m_nft_class m_nft_token))
transfer_type = "nft_mint"
entity_type = "nft"
nft_token = "NFT" # token 缩写
nft_id = "001" # NFT ID
end
transfer = {
asset: "unknown #62bc",
capacity: cell_output.capacity.to_s,
entity_type: entity_type,
transfer_type: transfer_type,
unit = token_unit(parsed_output)
address = parsed_output.address_hash
udt_info = parsed_output.udt_info

if (cell_capacity = cell_capacities[[address, unit]]).blank?
capacity = unit == "CKB" ? parsed_output.capacity.to_f : 0.0
cell_capacity = {
capacity: capacity,
cell_type: parsed_output.cell_type,
udt_info: {
symbol: udt_info&.symbol,
amount: udt_info&.amount.to_f,
decimal: udt_info&.decimal,
type_hash: udt_info&.type_hash,
published: !!udt_info&.published,
display_name: udt_info&.display_name,
uan: udt_info&.uan
}
}
transfers.push(transfer)
elsif unit == "CKB"
cell_capacity[:capacity] += parsed_output.capacity.to_f
else
cell_capacity[:udt_info][:amount] += udt_info.amount.to_f
end
address = Address.find address_id.address_id
data = {
address: address.address_hash,
transfers: transfers
}
transaction_data.push(data)

cell_capacities[[address, unit]] = cell_capacity
end
return transaction_data

cell_capacities
end

def get_nervos_dao_withdrawing_data
nervos_dao_deposit_cell = @transaction.cell_inputs.order(:id)[cell_output.cell_index].previous_cell_output
compensation_started_block = Block.find(nervos_dao_deposit_cell.block.id)
compensation_ended_block = Block.select(:number, :timestamp).find(@transaction.block_id)
interest = CkbUtils.dao_interest(cell_output)
interest_data = {
compensation_started_block_number: compensation_started_block.number.to_s,
compensation_ended_block_number: compensation_ended_block.number.to_s,
compensation_started_timestamp: compensation_started_block.timestamp.to_s,
compensation_ended_timestamp: compensation_ended_block.timestamp.to_s,
interest: interest,
locked_until_block_timestamp: @transaction.block.timestamp,
locked_until_block_number: @transaction.block.number,
}
return interest_data
def build_transfers(input_capacities, output_capacities)
capacities = Hash.new { |hash, key| hash[key] = [] }
keys = input_capacities.keys | output_capacities.keys
keys.each do |key|
address_hash, unit = key
input = input_capacities[key]
output = output_capacities[key]

# There may be keys in both input_capacities and output_capacities that do not exist
cell_type = output[:cell_type] || input[:cell_type]
capacity_change = output[:capacity].to_f - input[:capacity].to_f

transfer = { capacity: capacity_change, cell_type: cell_type }
if unit != "CKB"
output_amount = output[:udt_info] ? output[:udt_info][:amount] : 0.0
input_amount = input[:udt_info] ? input[:udt_info][:amount] : 0.0
amount_change = output_amount - input_amount
transfer[:udt_info] = output[:udt_info] || input[:udt_info]
transfer[:udt_info][:amount] = amount_change
end

capacities[address_hash] << CkbUtils.hash_value_to_s(transfer)
end

capacities.map do |address, value|
{ address: address, transfers: value }
end
end

def token_unit(cell)
if (udt_info = cell.udt_info).present?
udt_info.type_hash
else
"CKB"
end
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/api/v2/nft/transfers_controller.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
require "csv"
module Api
module V2
module NFT
Expand Down Expand Up @@ -29,6 +28,7 @@ def index
scope = scope.where(from: from) if from
scope = scope.where(to: to) if to
scope = scope.where(action: params[:transfer_action]) if params[:transfer_action]
scope = scope.includes(:ckb_transaction).where(ckb_transaction: { tx_hash: params[:tx_hash] }) if params[:tx_hash]
scope = scope.order(transaction_id: :desc)
pagy, token_transfers = pagy(scope)

Expand Down
26 changes: 15 additions & 11 deletions app/jobs/csv_exportable/export_address_transactions_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,19 @@ def perform(args)
tx_ids = tx_ids.where("ckb_transactions.block_number <= ?", args[:end_number])
end

ckb_transactions = CkbTransaction.includes(:inputs, :outputs).
select(:id, :tx_hash, :transaction_fee, :block_id, :block_number, :block_timestamp, :updated_at).
where(id: tx_ids.pluck(:ckb_transaction_id))
ckb_transactions = CkbTransaction.where(id: tx_ids.pluck(:ckb_transaction_id))

rows = []
ckb_transactions.find_in_batches(batch_size: 1000, order: :desc) do |transactions|
ckb_transactions.find_in_batches(batch_size: 500, order: :desc) do |transactions|
tx_ids = transactions.pluck(:id)
inputs = CellOutput.where(consumed_by_id: tx_ids, address_id: args[:address_id])
outputs = CellOutput.where(ckb_transaction_id: tx_ids, address_id: args[:address_id])

transactions.each do |transaction|
row = generate_row(transaction, args[:address_id])
tx_inputs = inputs.select { |input| input.consumed_by_id == transaction.id }.sort_by(&:id)
tx_outputs = outputs.select { |output| output.ckb_transaction_id == transaction.id }.sort_by(&:id)

row = generate_row(transaction, tx_inputs, tx_outputs)
next if row.blank?

rows += row
Expand All @@ -46,23 +51,22 @@ def perform(args)
generate_csv(header, rows)
end

def generate_row(transaction, address_id)
inputs = transaction.inputs.where(address_id: address_id).order(id: :asc)
outputs = transaction.outputs.where(address_id: address_id).order(id: :asc)

def generate_row(transaction, inputs, outputs)
input_capacities = cell_capacities(inputs)
output_capacities = cell_capacities(outputs)

datetime = datetime_utc(transaction.block_timestamp)
fee = parse_transaction_fee(transaction.transaction_fee)

rows = []
(input_capacities.keys | output_capacities.keys).each do |unit|
units = input_capacities.keys | output_capacities.keys
units.each do |unit|
token_in = input_capacities[unit]
token_out = output_capacities[unit]

balance_change = token_out.to_f - token_in.to_f
method = balance_change.positive? ? "PAYMENT RECEIVED" : "PAYMENT SENT"
display_fee = units.length == 1 || (units.length > 1 && unit == "CKB")

rows << [
transaction.tx_hash,
Expand All @@ -73,7 +77,7 @@ def generate_row(transaction, address_id)
(token_in || "/"),
(token_out || "/"),
balance_change,
(unit == "CKB" ? fee : "/"),
(display_fee ? fee : "/"),
datetime
]
end
Expand Down
5 changes: 3 additions & 2 deletions app/jobs/import_transaction_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -98,17 +98,18 @@ def perform(tx_hash, extra_data = {})
)
cell.lock_script = lock
cell.type_script = t
cell.data = output_data
cell.update!(
address_id: lock.address_id,
capacity: output.capacity,
occupied_capacity: cell.calculate_min_capacity,
status: "pending"
)

puts "output cell created tx_hash: #{tx_hash}, index: #{index}, cell_id: #{cell.id}"
# after the cell is created, create a datum
if output_data.present? && output_data != "0x"
(cell.cell_datum || cell.build_cell_datum).update(data: [output_data[2..]].pack("H*"))
end

process_output cell
process_deployed_cell(cell.lock_script)
process_deployed_cell(cell.type_script) if cell.type_script
Expand Down
7 changes: 7 additions & 0 deletions app/lib/api/v1/exceptions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,13 @@ def initialize
super code: 1029, status: 404, title: "Script not found", detail: "Script not found", href: "https://nervosnetwork.github.io/ckb-explorer/public/api_doc.html"
end
end

class UdtInfoInvalidError < Error
def initialize(detail)
super code: 1030, status: 400, title: "UDT info parameters invalid", detail: detail, href: "https://nervosnetwork.github.io/ckb-explorer/public/api_doc.html"
end
end

end
end
end
2 changes: 1 addition & 1 deletion app/models/deployed_cell.rb
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def self.create_initial_data_for_ckb_transaction(ckb_transaction, cell_deps)
by_type_hash = {}
by_data_hash = {}

# intialize cell dependencies records
# initialize cell dependencies records
# the `cell_deps` field in ckb transactions stores the contract cell (referred by out point,
# which contains the compiled byte code of contract) the transaction should refer.
# the submitter of the transaction is responsible for including all the contract cells
Expand Down
1 change: 1 addition & 0 deletions app/models/udt.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ def type_script
# display_name :string
# uan :string
# h24_ckb_transactions_count :bigint default(0)
# contact_info :string
#
# Indexes
#
Expand Down
2 changes: 2 additions & 0 deletions app/services/charts/daily_statistic_generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ def call
daily_statistic.reset!(updated_attrs)

daily_statistic
rescue Exception => e
NewRelic::Agent.notice_error(e.message)
end

private
Expand Down
2 changes: 1 addition & 1 deletion config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
resources :block_statistics, only: :show ## TODO: unused route
resources :epoch_statistics, only: :show
resources :market_data, only: :show
resources :udts, only: %i(index show) do
resources :udts, only: %i(index show update) do
collection do
get :download_csv
end
Expand Down
7 changes: 6 additions & 1 deletion config/routes/v2.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
namespace :api do
namespace :v2 do
post "/das_accounts" => "das_accounts#query", as: :das_accounts
resources :transactions, only: [:index, :show] do
resources :ckb_transactions, only: [:index, :show] do
member do
get :details
end
end
resources :transactions do
member do
get :raw
get :details
end
end
resources :pending_transactions, only: [:index] do
Expand Down
5 changes: 5 additions & 0 deletions db/migrate/20230808020637_add_contact_info_to_udts.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddContactInfoToUdts < ActiveRecord::Migration[7.0]
def change
add_column :udts, :contact_info, :string
end
end
6 changes: 4 additions & 2 deletions db/structure.sql
Original file line number Diff line number Diff line change
Expand Up @@ -2223,7 +2223,8 @@ CREATE TABLE public.udts (
nrc_factory_cell_id bigint,
display_name character varying,
uan character varying,
h24_ckb_transactions_count bigint DEFAULT 0
h24_ckb_transactions_count bigint DEFAULT 0,
contact_info character varying
);


Expand Down Expand Up @@ -4667,6 +4668,7 @@ INSERT INTO "schema_migrations" (version) VALUES
('20230622143339'),
('20230630112234'),
('20230711040233'),
('20230802015907');
('20230802015907'),
('20230808020637');


Loading
Loading