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 mainnet #1614

Merged
merged 5 commits into from
Feb 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -125,3 +125,5 @@ gem "kredis"
gem "async-websocket", "~> 0.22.1", require: false
gem "ecdsa"
gem "jwt"

gem "active_interaction", "~> 5.3"
4 changes: 4 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ GEM
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.1, >= 1.2.0)
active_interaction (5.3.0)
activemodel (>= 5.2, < 8)
activesupport (>= 5.2, < 8)
activejob (7.0.4)
activesupport (= 7.0.4)
globalid (>= 0.3.6)
Expand Down Expand Up @@ -475,6 +478,7 @@ PLATFORMS
x86_64-linux

DEPENDENCIES
active_interaction (~> 5.3)
activerecord-import
after_commit_everywhere
annotate
Expand Down
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
16 changes: 12 additions & 4 deletions app/controllers/api/v2/base_controller.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
module Api
module V2
class BaseController < ActionController::API
wrap_parameters false

include Pagy::Backend

rescue_from ActiveInteraction::InvalidInteractionError, with: :handle_params_error
rescue_from Api::V2::Exceptions::Error, with: :api_error

def handle_params_error(error)
error = Api::V2::Exceptions::ParamsInvalidError.new(error.message.squish.to_s)
api_error(error)
end

def api_error(error)
render json: RequestErrorSerializer.new([error], message: error.title), status: error.status
end

def address_to_lock_hash(address)
if address.start_with?("0x")
address
Expand All @@ -19,10 +31,6 @@ def pagy_get_items(collection, pagy)
collection.offset(pagy.offset).limit(pagy.items).fast_page
end

def api_error(error)
render json: RequestErrorSerializer.new([error], message: error.title), status: error.status
end

attr_reader :current_user

def validate_jwt!
Expand Down
61 changes: 4 additions & 57 deletions app/controllers/api/v2/portfolio/ckb_transactions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,12 @@ module V2
module Portfolio
class CkbTransactionsController < BaseController
before_action :validate_jwt!
before_action :pagination_params

def index
expires_in 15.minutes, public: true, stale_while_revalidate: 5.minutes, stale_if_error: 5.minutes
json = Users::CkbTransactions.run!(transaction_list_params.merge({ user: current_user, request: }))

account_books = sort_account_books(filter_account_books).page(@page).per(@page_size).fast_page
ckb_transactions = CkbTransaction.where(id: account_books.map(&:ckb_transaction_id)).
select(:id, :tx_hash, :block_id, :block_number, :block_timestamp,
:is_cellbase, :updated_at, :capacity_involved).
order(id: :desc)
options = FastJsonapi::PaginationMetaGenerator.new(
request: request,
records: ckb_transactions,
page: @page,
page_size: @page_size,
records_counter: account_books
).call
ckb_transaction_serializer = CkbTransactionsSerializer.new(
ckb_transactions,
options.merge(params: {
previews: true,
address: current_user.addresses
})
)
json = ckb_transaction_serializer.serialized_json

render json: json
render json:
end

def download_csv
Expand All @@ -42,40 +21,8 @@ def download_csv

private

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

def filter_account_books
address_ids =
if params[:address_hash].present?
address = Address.find_address!(params[:address_hash])
[address.id]
else
current_user.address_ids
end
scope = AccountBook.joins(:ckb_transaction).where(
account_books: { address_id: address_ids },
ckb_transactions: { tx_status: "committed" }
)

if params[:tx_hash].present?
scope = scope.where(ckb_transactions: { tx_hash: params[:tx_hash] })
end

scope
end

def sort_account_books(records)
sort, order = params.fetch(:sort, "ckb_transaction_id.desc").split(".", 2)
sort = "ckb_transactions.block_timestamp" if sort == "time"

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

records.order("#{sort} #{order}")
def transaction_list_params
params.permit(:address_hash, :tx_hash, :sort, :page, :page_size)
end

def download_params
Expand Down
21 changes: 4 additions & 17 deletions app/controllers/api/v2/portfolio/sessions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,16 @@ module Api
module V2
module Portfolio
class SessionsController < BaseController
before_action :validate_query_params

def create
user = User.find_or_create_by(identifier: params[:address])
payload = { uuid: user.uuid }
json = Users::SignIn.run!(sign_in_params)

render json: {
name: user.name,
jwt: PortfolioUtils.generate_jwt(payload)
}
render json:
end

private

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

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

render json: errors, status: status
end
def sign_in_params
params.permit(:address, :message, :signature, :pub_key)
end
end
end
Expand Down
31 changes: 3 additions & 28 deletions app/controllers/api/v2/portfolio/statistics_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,12 @@ module Api
module V2
module Portfolio
class StatisticsController < BaseController
before_action :validate_jwt!, :check_addresses_consistent!
before_action :validate_jwt!

def index
expires_in 30.minutes, public: true, stale_while_revalidate: 10.minutes, stale_if_error: 10.minutes

addresses = current_user.addresses
balance = addresses.pluck(:balance).sum
balance_occupied = addresses.pluck(:balance_occupied).sum
dao_deposit = addresses.pluck(:dao_deposit).sum
interest = addresses.pluck(:interest).sum
unclaimed_compensation = addresses.pluck(:unclaimed_compensation).sum

json = {
balance: balance.to_s,
balance_occupied: balance_occupied.to_s,
dao_deposit: dao_deposit.to_s,
interest: interest.to_s,
dao_compensation: (interest.to_i + unclaimed_compensation.to_i).to_s
}

render json: { data: json }
end

private

def check_addresses_consistent!
address = Address.find_by_address_hash(params[:latest_address])
unless current_user.portfolios.exists?(address: address)
latest_address = current_user.portfolios.last&.address
raise Api::V2::Exceptions::PortfolioLatestDiscrepancyError.new(latest_address&.address_hash)
end
data = Users::Statistics.run!({ user: current_user, latest_address: params[:latest_address] })
render json: { data: }
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/api/v2/portfolio/users_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ class UsersController < BaseController
before_action :validate_jwt!

def update
current_user.update(name: params[:name])
Users::Update.run!({ user: current_user, name: params[:name] })

head :no_content
end
Expand Down
13 changes: 10 additions & 3 deletions app/controllers/api/v2/scripts_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
module Api
module V2
class ScriptsController < BaseController
before_action :set_page_and_page_size
before_action :find_script
before_action :set_page_and_page_size, except: :referring_capacities
before_action :find_script, except: :referring_capacities

def general_info
head :not_found and return if @script.blank? || @contract.blank?
Expand Down Expand Up @@ -49,6 +49,13 @@ def referring_cells
end
end

def referring_capacities
expires_in 15.seconds, public: true, must_revalidate: true, stale_while_revalidate: 5.seconds
data = Contract.all.map { { _1.code_hash => _1.total_referring_cells_capacity.to_s } }

render json: { data: }
end

private

def get_script_content
Expand All @@ -69,7 +76,7 @@ def get_script_content
capacity_of_referring_cells: @contract.total_referring_cells_capacity,
count_of_transactions: @contract.ckb_transactions_count,
count_of_deployed_cells: @contract.deployed_cells_count,
count_of_referring_cells: @contract.referring_cells_count
count_of_referring_cells: @contract.referring_cells_count,
}
end

Expand Down
8 changes: 4 additions & 4 deletions app/controllers/validations/portfolio_signature.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ class PortfolioSignature
validate :signature_must_be_valid

def initialize(params = {})
@address = params[:address]
@message = params[:message]
@signature = params[:signature]
@pub_key = params[:pub_key]
@address = params[:address].to_s
@message = params[:message].to_s
@signature = params[:signature].to_s
@pub_key = params[:pub_key].to_s
end

def error_object
Expand Down
64 changes: 64 additions & 0 deletions app/interactions/users/ckb_transactions.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
module Users
class CkbTransactions < ActiveInteraction::Base
include Api::V2::Exceptions

object :user
object :request, class: ActionDispatch::Request
string :address_hash, default: nil
string :tx_hash, default: nil
string :sort, default: "ckb_transaction_id.desc"
integer :page, default: 1
integer :page_size, default: CkbTransaction.default_per_page

def execute
account_books = sort_account_books(filter_account_books).page(page).per(page_size).fast_page
transactions = CkbTransaction.where(id: account_books.map(&:ckb_transaction_id)).
select(:id, :tx_hash, :block_id, :block_number, :block_timestamp,
:is_cellbase, :updated_at, :capacity_involved).
order(id: :desc)

options = FastJsonapi::PaginationMetaGenerator.new(
records: transactions,
records_counter: account_books,
request:,
page:,
page_size:,
).call
options[:params] = { previews: true, address: user.addresses }

transactions_serializer = CkbTransactionsSerializer.new(transactions, options)
transactions_serializer.serialized_json
end

private

def filter_account_books
address_ids = user.address_ids
if address_hash.present?
address = Address.find_address!(address_hash)
address_ids = Array[address.id]
end

scope = AccountBook.joins(:ckb_transaction).where(
account_books: { address_id: address_ids },
ckb_transactions: { tx_status: "committed" },
)
scope = scope.where(ckb_transactions: { tx_hash: }) if tx_hash.present?

scope
rescue StandardError
raise AddressNotFoundError.new
end

def sort_account_books(records)
sorting, ordering = sort.split(".", 2)
sorting = "ckb_transactions.block_timestamp" if sorting == "time"

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

records.order("#{sorting} #{ordering}")
end
end
end
Loading
Loading