Skip to content

Commit

Permalink
DigixGlobal#70 watching_transaction model watch and resend refactored…
Browse files Browse the repository at this point in the history
…, query fix
  • Loading branch information
bshevchenko committed Sep 5, 2019
1 parent d74ad40 commit 84cb85a
Show file tree
Hide file tree
Showing 8 changed files with 295 additions and 250 deletions.
36 changes: 19 additions & 17 deletions app/graphql/mutations/resend_transaction_mutation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,40 +24,42 @@ class ResendTransactionMutation < Types::Base::BaseMutation
Operation Errors:
- Previous transaction not found
- Unauthorized action
- Nonce is not the same as the previous
EOS

def resolve(id:, transaction_object:, signed_transaction:)
key = :watched_transaction

old = WatchingTransaction.find(id)

user = context.fetch(:current_user, nil)
unless user.id == old.user.id
return form_error(key, 'id', 'Unauthorized action')
unless (old = WatchingTransaction.find_by(id: id))
return form_error(key, 'transaction_object', 'Previous transaction not found')
end

transaction_object = JSON.parse(transaction_object)

unless old.transaction_object['nonce'] == transaction_object['nonce']
return form_error(key, 'transaction_object', 'Nonce is not the same as the previous')
end
attrs = {
transaction_object: JSON.parse(transaction_object),
signed_transaction: signed_transaction
}

result, tx_or_errors = WatchingTransaction.watch(
context.fetch(:current_user),
transaction_object,
signed_transaction,
id
result, tx_or_errors = WatchingTransaction.resend(
context.fetch(:current_user, nil),
old,
attrs
)

form_error(key, 'id', 'Unauthorized action')

case result
when :invalid_transaction_object
form_error(key, 'transaction_object', 'Invalid transaction object')
when :unauthorized_action
form_error(key, 'id', 'Unauthorized action')
when :invalid_nonce
form_error(key, 'transaction_object', 'Nonce is not the same as the previous')
when :invalid_data
model_errors(key, tx_or_errors)
when :ok
model_result(key, tx_or_errors)
end
rescue ActiveRecord::RecordNotFound
form_error(key, 'transaction_object', 'Previous transaction not found')
end

def self.authorized?(object, context)
Expand Down
18 changes: 13 additions & 5 deletions app/graphql/mutations/watch_transaction_mutation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,29 @@ class WatchTransactionMutation < Types::Base::BaseMutation
description: 'Newly created transaction'
field :errors, [UserErrorType],
null: false,
description: 'Mutation errors'
description: <<~EOS
Mutation errors
Operation Errors:
- Invalid transaction object
EOS

def resolve(transaction_object:, signed_transaction:)
key = :watched_transaction

transaction_object = JSON.parse(transaction_object)
attrs = {
transaction_object: JSON.parse(transaction_object),
signed_transaction: signed_transaction
}

result, tx_or_errors = WatchingTransaction.watch(
context.fetch(:current_user),
transaction_object,
signed_transaction,
nil
attrs
)

case result
when :invalid_transaction_object
form_error(key, 'transaction_object', 'Invalid transaction object')
when :invalid_data
model_errors(key, tx_or_errors)
when :ok
Expand Down
4 changes: 3 additions & 1 deletion app/graphql/resolvers/watched_transaction_resolver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ class WatchedTransactionResolver < Resolvers::Base
description: 'Find the last watched transaction in the group with that txhash'

def resolve(txhash:)
tx = WatchingTransaction.find_by(txhash: txhash)
unless (tx = WatchingTransaction.find_by(txhash: txhash))
raise GraphQL::ExecutionError, "Transaction with hash #{txhash} does not exist"
end
WatchingTransaction.find_by(group_id: tx.group_id).last
end

Expand Down
4 changes: 4 additions & 0 deletions app/graphql/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -1716,6 +1716,7 @@ type ResendTransactionMutationPayload {
Operation Errors:
- Previous transaction not found
- Unauthorized action
- Nonce is not the same as the previous
"""
errors: [UserError!]!
Expand Down Expand Up @@ -2520,6 +2521,9 @@ type WatchTransactionMutationPayload {

"""
Mutation errors
Operation Errors:
- Invalid transaction object
"""
errors: [UserError!]!

Expand Down
48 changes: 39 additions & 9 deletions app/models/watching_transaction.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,43 @@ def txhash=(value)
end

class << self
def watch(user, transaction_object, signed_transaction, group_id)
def watch(user, attrs)
transaction_object = attrs.fetch(:transaction_object, nil)
unless transaction_object.is_a?(Hash)
return [:invalid_transaction_object, nil]
end

tx = WatchingTransaction.new(
user: user,
transaction_object: transaction_object,
signed_transaction: attrs.fetch(:signed_transaction, nil),
txhash: transaction_object.fetch('transactionHash', nil)
)

return [:invalid_data, tx.errors] unless tx.valid?
return [:database_error, tx.errors] unless tx.save

[:ok, tx]
end

def resend(user, watching_transaction, attrs)
transaction_object = attrs.fetch(:transaction_object, nil)
unless transaction_object.is_a?(Hash)
return [:invalid_transaction_object, nil]
end
unless user.id == watching_transaction.user.id
return [:unauthorized_action, nil]
end
unless transaction_object.fetch('nonce') == watching_transaction.transaction_object.fetch('nonce')
return [:invalid_nonce, nil]
end

tx = WatchingTransaction.new(
user: user,
transaction_object: transaction_object,
signed_transaction: signed_transaction,
txhash: transaction_object['transactionHash'],
group_id: group_id
signed_transaction: attrs.fetch(:signed_transaction, nil),
txhash: transaction_object.fetch('transactionHash', nil),
group_id: watching_transaction.id
)

return [:invalid_data, tx.errors] unless tx.valid?
Expand All @@ -50,27 +80,27 @@ def watch(user, transaction_object, signed_transaction, group_id)
[:ok, tx]
end

def resend
def resend_transactions
WatchingTransaction.find_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
ok_send, txhash = EthereumApi.send_raw_transaction(tx.signed_transaction)
if ok_send == :ok
puts "Resent transaction #{tx.txhash}, new hash is #{txhash}"
Rails.logger.info "Resent transaction #{tx.txhash}, new hash is #{txhash}"
tx.transaction_object['transactionHash'] = txhash
tx.update_attributes(txhash: txhash, transaction_object: tx.transaction_object)
else
puts "Failed to resend #{tx.txhash}"
Rails.logger.info "Failed to resend #{tx.txhash}"
end
else
puts "Destroying transaction #{tx.txhash}"
Rails.logger.info "Destroying transaction #{tx.txhash}"
tx.destroy
end
end

unless data['blockNumber'].nil?
puts "Destroying transactions from group #{tx.group_id}"
Rails.logger.info "Destroying transactions from group #{tx.group_id}"
WatchingTransaction.find_by(group_id: tx.group_id).destroy
end
end
Expand Down
2 changes: 1 addition & 1 deletion db/migrate/20190826132750_create_watching_transactions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ class CreateWatchingTransactions < ActiveRecord::Migration[5.2]
def change
create_table :watching_transactions, id: false do |t|
t.string :id, limit: 36, primary_key: true, null: false
t.string :group_id, limit: 36, index: true, null: true
t.string :group_id, limit: 36, index: true, null: false
t.string :transaction_object, null: false
t.string :signed_transaction, null: false
t.string :txhash
Expand Down

0 comments on commit 84cb85a

Please sign in to comment.