Skip to content

Commit

Permalink
DigixGlobal#70 tests for WatchingTransaction model, including resend_…
Browse files Browse the repository at this point in the history
…transactions made for cron
  • Loading branch information
bshevchenko committed Sep 10, 2019
1 parent b8125e0 commit cc7c332
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 12 deletions.
2 changes: 1 addition & 1 deletion app/graphql/mutations/resend_transaction_mutation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def resolve(id:, transaction_hash:, transaction_object:, signed_transaction:)
end

attrs = {
transaction_hash: transaction_hash,
txhash: transaction_hash,
transaction_object: transaction_object,
signed_transaction: signed_transaction
}
Expand Down
2 changes: 1 addition & 1 deletion app/graphql/mutations/watch_transaction_mutation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def resolve(transaction_hash:, transaction_object:, signed_transaction:)
key = :watched_transaction

attrs = {
transaction_hash: transaction_hash,
txhash: transaction_hash,
transaction_object: transaction_object,
signed_transaction: signed_transaction
}
Expand Down
17 changes: 9 additions & 8 deletions app/models/watching_transaction.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def watch(user, attrs)
user: user,
transaction_object: attrs.fetch(:transaction_object, nil),
signed_transaction: attrs.fetch(:signed_transaction, nil),
txhash: attrs.fetch(:transaction_hash, nil)
txhash: attrs.fetch(:txhash, nil)
)

return [:invalid_data, tx.errors] unless tx.valid?
Expand All @@ -52,15 +52,15 @@ def resend(user, watching_transaction, attrs)
unless user.id == watching_transaction.user.id
return [:unauthorized_action, nil]
end
unless transaction_object.fetch('nonce') == watching_transaction.transaction_object['nonce']
unless transaction_object.fetch('nonce', nil) == watching_transaction.transaction_object['nonce']
return [:invalid_nonce, nil]
end

tx = WatchingTransaction.new(
user: user,
transaction_object: transaction_object,
signed_transaction: attrs.fetch(:signed_transaction, nil),
txhash: attrs.fetch(:transaction_hash, nil),
txhash: attrs.fetch(:txhash, nil),
group_id: watching_transaction.group_id
)

Expand All @@ -71,10 +71,10 @@ def resend(user, watching_transaction, attrs)
end

def resend_transactions
WatchingTransaction.find_each do |tx|
WatchingTransaction.all.order('created_at ASC').each do |tx|
ok_tx, data = EthereumApi.get_transaction_by_hash(tx.txhash)
unless ok_tx == :ok && data
if WatchingTransaction.find_by(group_id: tx.group_id).count == 1
if WatchingTransaction.where(group_id: tx.group_id).count == 1
ok_send, txhash = EthereumApi.send_raw_transaction(tx.signed_transaction)
if ok_send == :ok
Rails.logger.info "Resent transaction #{tx.txhash}, new hash is #{txhash}"
Expand All @@ -83,14 +83,15 @@ def resend_transactions
Rails.logger.info "Failed to resend #{tx.txhash}"
end
else
Rails.logger.info "Destroying transaction #{tx.txhash}"
Rails.logger.info "Destroying dropped transaction #{tx.txhash}"
tx.destroy
end
next
end

unless data['block_number'].nil?
Rails.logger.info "Destroying transactions from group #{tx.group_id}"
WatchingTransaction.find_by(group_id: tx.group_id).destroy
Rails.logger.info "Destroying transactions from mined group #{tx.group_id}"
WatchingTransaction.where(group_id: tx.group_id).destroy_all
end
end
end
Expand Down
4 changes: 2 additions & 2 deletions test/factories/watching_transactions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@

FactoryBot.define do
sequence(:transaction_object) do |_|
{ nonce: Random.rand(1..1000) }
{ 'nonce' => Random.rand(1..1000) }
end
sequence(:fixed_transaction_object) do |_|
{ nonce: static_nonce }
{ 'nonce' => static_nonce }
end
sequence(:signed_transaction) { |_| SecureRandom.hex(32) }
sequence(:id) { |_| SecureRandom.hex(32) }
Expand Down
91 changes: 91 additions & 0 deletions test/models/watching_transaction_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,95 @@ class WatchingTransactionTest < ActiveSupport::TestCase
assert_not WatchingTransaction.new(params).save,
'should fail with the same data'
end

test 'watch should work' do
user = create(:user)
attrs = attributes_for(:watching_transaction)
ok, tx = WatchingTransaction.watch(user, attrs)

assert_equal :ok, ok,
'should work'
end

test 'resend should work' do
user = create(:user)
watching_transaction = create(:watching_transaction, user: user)
attrs = attributes_for(:watching_transaction)

ok, tx = WatchingTransaction.resend(user, watching_transaction, attrs)

assert_equal :ok, ok,
'should work'
end

test 'resend_transactions' do
original_transaction = FactoryBot.create(:watching_transaction)
group_id = original_transaction.group_id
4.times do
FactoryBot.create(:watching_transaction, group_id: group_id)
end
latest_transaction = FactoryBot.create(:watching_transaction, group_id: group_id)

stub_request(:post, EthereumApi::SERVER_URL)
.with(body: /eth_getTransactionByHash/)
.to_return(
body: {
result: {
'block_number' => nil,
}
}.to_json
)

WatchingTransaction.resend_transactions

assert_equal 6, WatchingTransaction.where(group_id: group_id).count,
'should keep all if none is mined'

stub_request(:post, EthereumApi::SERVER_URL)
.with(body: /eth_getTransactionByHash.*#{latest_transaction.txhash}/)
.to_return(
body: {
result: {
'block_number' => '0x1',
}
}.to_json
)

WatchingTransaction.resend_transactions

assert_equal 0, WatchingTransaction.where(group_id: group_id).count,
'should destroy all if one is mined'

4.times do
FactoryBot.create(:watching_transaction, group_id: group_id)
end
sleep 1 # UUID is not sortable, so some delay is needed in order to properly sort via created_at
latest_transaction = FactoryBot.create(:watching_transaction, group_id: group_id)

stub_request(:post, EthereumApi::SERVER_URL)
.with(body: /eth_getTransactionByHash/)
.to_return(
body: {
result: nil
}.to_json
)

new_txhash = generate(:txhash)
stub_request(:post, EthereumApi::SERVER_URL)
.with(body: /eth_sendRawTransaction/)
.to_return(
body: {
result: new_txhash
}.to_json
)

WatchingTransaction.resend_transactions

assert_equal 1, WatchingTransaction.where(group_id: group_id).count,
'should resend latest if rest are dropped'

resent_transaction = WatchingTransaction.find_by(id: latest_transaction.id)
assert_equal new_txhash, resent_transaction.txhash,
'should update txhash for resent transaction'
end
end

0 comments on commit cc7c332

Please sign in to comment.