Skip to content

Commit

Permalink
DigixGlobal#70 watch transaction: added JSON type, setter and getter;…
Browse files Browse the repository at this point in the history
… additional validates for model
  • Loading branch information
bshevchenko committed Sep 4, 2019
1 parent 5fe0550 commit a5af0f2
Show file tree
Hide file tree
Showing 9 changed files with 40 additions and 26 deletions.
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ gem 'devise_token_auth'
gem 'discard', '>= 1.0.0'
gem 'faker', '>= 1.9.1', require: false
gem 'graphiql-rails', '>= 1.5.0'
gem 'graphql', '1.9.2'
gem 'graphql', '1.9.5'
gem 'graphql-guard', '~> 1.2.1'
gem 'kaminari', '>= 1.1.1'
gem 'loofah', '>= 2.2.3'
Expand Down
4 changes: 2 additions & 2 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ GEM
graphiql-rails (1.7.0)
railties
sprockets-rails
graphql (1.9.2)
graphql (1.9.5)
graphql-guard (1.2.2)
graphql (>= 1.6.0, < 2)
hashdiff (0.4.0)
Expand Down Expand Up @@ -354,7 +354,7 @@ DEPENDENCIES
factory_bot_rails (>= 4.0.0)
faker (>= 1.9.1)
graphiql-rails (>= 1.5.0)
graphql (= 1.9.2)
graphql (= 1.9.5)
graphql-guard (~> 1.2.1)
kaminari (>= 1.1.1)
listen (>= 3.0.5, < 3.2)
Expand Down
7 changes: 3 additions & 4 deletions app/graphql/mutations/resend_transaction_mutation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class ResendTransactionMutation < Types::Base::BaseMutation
argument :id, String,
required: true,
description: 'ID of the transaction to be resent'
argument :transaction_object, String,
argument :transaction_object, GraphQL::Types::JSON,
required: true,
description: 'The JSONified transaction data object'
argument :signed_transaction, String,
Expand Down Expand Up @@ -37,10 +37,9 @@ def resolve(id:, transaction_object:, signed_transaction:)
return form_error(key, 'id', 'Unauthorized action')
end

old_data = JSON.parse(old.transaction_object)
data = JSON.parse(transaction_object)
transaction_object = JSON.parse(transaction_object)

unless old_data['nonce'] == data['nonce']
unless old.transaction_object['nonce'] == transaction_object['nonce']
return form_error(key, 'transaction_object', 'Nonce is not the same as the previous')
end

Expand Down
4 changes: 3 additions & 1 deletion app/graphql/mutations/watch_transaction_mutation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ module Mutations
class WatchTransactionMutation < Types::Base::BaseMutation
description 'Given a transaction, save it to the database to be resent'

argument :transaction_object, String,
argument :transaction_object, GraphQL::Types::JSON,
required: true,
description: 'The JSONified transaction data object'
argument :signed_transaction, String,
Expand All @@ -21,6 +21,8 @@ class WatchTransactionMutation < Types::Base::BaseMutation
def resolve(transaction_object:, signed_transaction:)
key = :watched_transaction

transaction_object = JSON.parse(transaction_object)

result, tx_or_errors = WatchingTransaction.watch(
context.fetch(:current_user),
transaction_object,
Expand Down
11 changes: 8 additions & 3 deletions app/graphql/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -792,6 +792,11 @@ Industry for KYC submission
"""
scalar IndustryValue

"""
Represents untyped JSON
"""
scalar JSON

"""
A customer's KYC submission
"""
Expand Down Expand Up @@ -1694,7 +1699,7 @@ input ResendTransactionMutationInput {
"""
The JSONified transaction data object
"""
transactionObject: String!
transactionObject: JSON!
}

"""
Expand Down Expand Up @@ -2501,7 +2506,7 @@ input WatchTransactionMutationInput {
"""
The JSONified transaction data object
"""
transactionObject: String!
transactionObject: JSON!
}

"""
Expand Down Expand Up @@ -2536,7 +2541,7 @@ type WatchedTransaction {
"""
The JSONified transaction data object
"""
transactionObject: String!
transactionObject: JSON!

"""
Signer of the transaction
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class WatchedTransactionType < Types::Base::BaseObject
null: false,
description: 'Signer of the transaction'

field :transaction_object, String,
field :transaction_object, GraphQL::Types::JSON,
null: false,
description: 'The JSONified transaction data object'
end
Expand Down
24 changes: 16 additions & 8 deletions app/models/watching_transaction.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,38 @@ class WatchingTransaction < ApplicationRecord
has_many :transactions, class_name: 'WatchingTransaction', foreign_key: 'group_id'
belongs_to :original, class_name: 'WatchingTransaction', foreign_key: 'group_id', optional: true

validates :transaction_object,
presence: true
validates :signed_transaction,
presence: true
validates :txhash,
presence: true,
uniqueness: true

def set_uuid
self.id = SecureRandom.uuid

self.group_id = id unless group_id
end

def transaction_object
JSON.parse(super)
end

def transaction_object=(value)
super(JSON.generate(value))
end

def txhash=(value)
super(value&.downcase)
end

class << self
def watch(user, transaction_object, signed_transaction, group_id)
data = JSON.parse(transaction_object)

tx = WatchingTransaction.new(
user: user,
transaction_object: transaction_object,
signed_transaction: signed_transaction,
txhash: data['transactionHash'],
txhash: transaction_object['transactionHash'],
group_id: group_id
)

Expand All @@ -39,7 +48,7 @@ def watch(user, transaction_object, signed_transaction, group_id)
[:ok, tx]
end

def resend # For 5 minute cron job
def resend
web3 = Web3::Eth::Rpc.new host: ENV.fetch('INFURA_SERVER_URL') { 'mainnet.infura.io' },
port: 443,
connect_options: {
Expand All @@ -55,9 +64,8 @@ def resend # For 5 minute cron job
unless data
if WatchingTransaction.find_by(group_id: tx.group_id).count == 1
receipt = web3.eth.sendSignedTransaction(tx.signed_transaction)
data = JSON.parse(tx.transaction_object)
data['transactionHash'] = receipt['transactionHash']
tx.update_attributes(txhash: receipt['transactionHash'], transaction_object: JSON.generate(data))
tx.transaction_object['transactionHash'] = receipt['transactionHash']
tx.update_attributes(txhash: receipt['transactionHash'], transaction_object: tx.transaction_object)
else
tx.destroy
end
Expand Down
8 changes: 4 additions & 4 deletions test/graphql/resend_transaction_mutation_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

class ResendTransactionMutationTest < ActiveSupport::TestCase
QUERY = <<~EOS
mutation($transactionObject: String!, $signedTransaction: String!) {
mutation($transactionObject: JSON!, $signedTransaction: String!) {
watchTransaction(input: { transactionObject: $transactionObject, signedTransaction: $signedTransaction }) {
watchedTransaction {
id
Expand All @@ -22,7 +22,7 @@ class ResendTransactionMutationTest < ActiveSupport::TestCase
EOS

QUERY2 = <<~EOS
mutation($id: String!, $transactionObject: String!, $signedTransaction: String!) {
mutation($id: String!, $transactionObject: JSON!, $signedTransaction: String!) {
resendTransaction(input: { id: $id, transactionObject: $transactionObject, signedTransaction: $signedTransaction }) {
watchedTransaction {
id
Expand Down Expand Up @@ -86,10 +86,10 @@ class ResendTransactionMutationTest < ActiveSupport::TestCase

data2 = tx2_result['data']['resendTransaction']['watchedTransaction']

assert_equal attrs['transactionObject'], data2['transactionObject'],
assert_equal transaction_object, data2['transactionObject'],
'transactionObject should be the same'

assert_equal JSON.parse(data['transactionObject'])['nonce'], JSON.parse(data2['transactionObject'])['nonce'],
assert_equal data['transactionObject']['nonce'], data2['transactionObject']['nonce'],
'nonce should be the same'
end

Expand Down
4 changes: 2 additions & 2 deletions test/graphql/watch_transaction_mutation_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

class WatchTransactionMutationTest < ActiveSupport::TestCase
QUERY = <<~EOS
mutation($transactionObject: String!, $signedTransaction: String!) {
mutation($transactionObject: JSON!, $signedTransaction: String!) {
watchTransaction(input: { transactionObject: $transactionObject, signedTransaction: $signedTransaction }) {
watchedTransaction {
id
Expand Down Expand Up @@ -45,7 +45,7 @@ class WatchTransactionMutationTest < ActiveSupport::TestCase

data = tx_result['data']['watchTransaction']['watchedTransaction']

assert_equal attrs['transactionObject'], data['transactionObject'],
assert_equal transaction_object, data['transactionObject'],
'transactionObject should be the same'
end

Expand Down

0 comments on commit a5af0f2

Please sign in to comment.