diff --git a/app/jobs/update_address_op_return_job.rb b/app/jobs/update_address_op_return_job.rb new file mode 100644 index 0000000..8fcd79e --- /dev/null +++ b/app/jobs/update_address_op_return_job.rb @@ -0,0 +1,57 @@ +class UpdateAddressOpReturnJob < ApplicationJob + queue_as :default + + OP_RETURN_RE = /\AOP_RETURN ([0-9a-fA-F]*)\z/.freeze + MIN_CONFIRMATIONS = 1 + + def perform(address) + return unless address.update_op_return? + + all_tx_datas = JSON.parse %x[dash-cli listtransactions "*" 100] + + tx_datas = all_tx_datas.select do |tx_data| + tx_data['address'] == address.value && + tx_data['category'] == 'send' && + tx_data['confirmations'] >= MIN_CONFIRMATIONS + end + + tx_ids = tx_datas.map { |tx_data| tx_data['txid'] }.uniq + + tx_full_datas = tx_ids.map do |tx_id| + JSON.parse %x[dash-cli getrawtransaction #{tx_id} 1] + end + + all_tx_vouts = tx_full_datas.flat_map do |tx_full_data| + tx_full_data['vout'].map do |vout| + tx_full_data.merge 'vout' => vout + end + end + + tx_vouts = all_tx_vouts.select do |tx_vout| + tx_vout['vout']['scriptPubKey'] != nil && + tx_vout['vout']['scriptPubKey']['asm'] != nil && + tx_vout['vout']['scriptPubKey']['asm'].match?(OP_RETURN_RE) + end + + if tx_vouts.empty? + address.update! op_return_value: nil, + op_return_updated_at: Time.zone.now + return + end + + actual_tx_vout = tx_vouts.sort_by do |tx_vout| + [ + tx_vout['confirmations'], + -tx_vout['vout']['n'], + ] + end.first + + asm = actual_tx_vout['vout']['scriptPubKey']['asm'] + match = OP_RETURN_RE.match asm + hex = match[1] + ascii = [hex].pack 'H*' + + address.update! op_return_value: ascii, + op_return_updated_at: Time.zone.now + end +end diff --git a/test/jobs/update_address_op_return_job_test.rb b/test/jobs/update_address_op_return_job_test.rb new file mode 100644 index 0000000..1d7ed38 --- /dev/null +++ b/test/jobs/update_address_op_return_job_test.rb @@ -0,0 +1,7 @@ +require "test_helper" + +class UpdateAddressOpReturnJobTest < ActiveJob::TestCase + # test "the truth" do + # assert true + # end +end