|
| 1 | +class UdtRelatedDataUpdater |
| 2 | + include Rake::DSL |
| 3 | + |
| 4 | + def initialize |
| 5 | + namespace :migration do |
| 6 | + desc "Usage: bundle exec rake 'migration:update_udt_related_data[true, true]'" |
| 7 | + task :update_udt_related_data, [:create_udt, :create_udt_accounts] => :environment do |_, args| |
| 8 | + create_udts if args[:create_udt].downcase == "true" |
| 9 | + if args[:create_udt_accounts].downcase == "true" |
| 10 | + udt_infos = CellOutput.udt.pluck(:type_hash, :address_id).uniq |
| 11 | + create_udt_accounts(udt_infos) |
| 12 | + update_udt_info(udt_infos) |
| 13 | + end |
| 14 | + update_related_tx_caches |
| 15 | + |
| 16 | + puts "done" |
| 17 | + end |
| 18 | + end |
| 19 | + end |
| 20 | + |
| 21 | + private |
| 22 | + |
| 23 | + def update_udt_info(udt_infos) |
| 24 | + type_hashes = udt_infos.map { |udt_info| udt_info[0] }.uniq |
| 25 | + columns = %i(type_hash total_amount addresses_count) |
| 26 | + amount_hashes = UdtAccount.where(type_hash: type_hashes).group(:type_hash).sum(:amount) |
| 27 | + addresses_count_hashes = UdtAccount.where(type_hash: type_hashes).group(:type_hash).count(:address_id) |
| 28 | + import_values = |
| 29 | + type_hashes.map do |type_hash| |
| 30 | + [type_hash, amount_hashes[type_hash], addresses_count_hashes[type_hash]] |
| 31 | + end |
| 32 | + |
| 33 | + Udt.import columns, import_values, validate: false, on_duplicate_key_update: { conflict_target: [:type_hash], columns: [:total_amount, :addresses_count] } |
| 34 | + |
| 35 | + puts "udt info updated" |
| 36 | + end |
| 37 | + |
| 38 | + def create_udt_accounts(udt_infos) |
| 39 | + udt_accounts = |
| 40 | + udt_infos.map do |info| |
| 41 | + address = Address.find(info[1]) |
| 42 | + udt_live_cell_data = address.cell_outputs.live.udt.where(type_hash: info[0]).pluck(:data) |
| 43 | + amount = udt_live_cell_data.map { |data| CkbUtils.parse_udt_cell_data(data) }.sum |
| 44 | + udt = Udt.find_or_create_by!(type_hash: info[0], code_hash: ENV["SUDT_CELL_TYPE_HASH"], udt_type: "sudt") |
| 45 | + { udt_id: udt.id, udt_type: Udt.udt_types[udt.udt_type], full_name: udt.full_name, symbol: udt.symbol, decimal: udt.decimal, published: udt.published, code_hash: udt.code_hash, type_hash: udt.type_hash, amount: amount, address_id: address.id, created_at: Time.now, updated_at: Time.now } |
| 46 | + end |
| 47 | + |
| 48 | + UdtAccount.upsert_all(udt_accounts, unique_by: :index_udt_accounts_on_type_hash_and_address_id) |
| 49 | + puts "udt accounts created" |
| 50 | + end |
| 51 | + |
| 52 | + def create_udts |
| 53 | + TypeScript.where(code_hash: ENV["SUDT_CELL_TYPE_HASH"]).each do |type_script| |
| 54 | + node_type = CKB::Types::Script.new(type_script.to_node_type) |
| 55 | + type_script.cell_output.update(cell_type: "udt") |
| 56 | + Udt.find_or_create_by!(args: type_script.args, hash_type: type_script.hash_type, type_hash: node_type.compute_hash, code_hash: ENV["SUDT_CELL_TYPE_HASH"], udt_type: "sudt") |
| 57 | + end |
| 58 | + |
| 59 | + puts "udts created" |
| 60 | + end |
| 61 | + |
| 62 | + |
| 63 | + def update_related_tx_caches |
| 64 | + type_scripts = TypeScript.where(code_hash: ENV["SUDT_CELL_TYPE_HASH"]) |
| 65 | + type_hashes = type_scripts.map {|type_script| CKB::Types::Script.new(type_script.to_node_type).compute_hash }.uniq |
| 66 | + tx_ids = CellOutput.where(type_hash: type_hashes).pluck(:ckb_transaction_id) |
| 67 | + tx_ids.each do |tx_id| |
| 68 | + Rails.cache.delete("normal_tx_display_outputs_previews_false_#{tx_id}") |
| 69 | + Rails.cache.delete("normal_tx_display_outputs_previews_true_#{tx_id}") |
| 70 | + Rails.cache.delete("normal_tx_display_inputs_previews_false_#{tx_id}") |
| 71 | + Rails.cache.delete("normal_tx_display_inputs_previews_true_#{tx_id}") |
| 72 | + end |
| 73 | + end |
| 74 | +end |
| 75 | + |
| 76 | +UdtRelatedDataUpdater.new |
0 commit comments