istox 0.1.81.pre.test10 → 0.1.81

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 137bc00193a848330fba21e01f23d89d9c06ff55604bf75e5d6368ea14bf0192
4
- data.tar.gz: 6cf96f0726fd3dc5680a9b332536613fc8da2679a2a965791b51c30bac66d580
3
+ metadata.gz: b9b67e7deab7a2a53ab80d237842554f21ca126e3542bf75dfbbb68a46961395
4
+ data.tar.gz: 913e6213c402f933ac375bb77999119131d25e0a886c5cf2819c8ed56685ba88
5
5
  SHA512:
6
- metadata.gz: 9b1071eb5a4d22a8763ae6d7255a3211f16f8fdff943226632229279b24f00941bf4efc83ee332960cc7b8bc189d2d45727ca303c1b231bd549cdd1e7598343e
7
- data.tar.gz: 3b72c52f64f0104c6f0d18a6875cd93cde6e249ac200dc6372551498bb6890c8370aa620d7bced6af1a94f7f9f6abb76b7d4547ca1cb3702ece300bef9e58913
6
+ metadata.gz: 6c02663da343a9b5efef558084c5a14f32c92900b055d3fc3041e71dec38a1fa828b2e8ed4aee8ef7f1c2f7eccc991bd11a24bb2e7300505b6b11e025ff4249d
7
+ data.tar.gz: a57ed4210294057d2ef6cbbb9dedab41b28e0a2f78f8f75e2d97d17f5afce0b3a9948f9aca7ad0a8b0d685bfd58ebbf08d0876a0236b0833ff100beed7595368
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- istox (0.1.81.pre.test9)
4
+ istox (0.1.80)
5
5
  binding_of_caller
6
6
  bunny (>= 2.12.0)
7
7
  graphlient
@@ -1,35 +1,34 @@
1
1
  require 'active_record'
2
2
  require 'paranoia'
3
- require 'gruf'
4
- require 'listen'
5
- require 'istox/version'
3
+ require "gruf"
4
+ require "listen"
5
+ require "istox/version"
6
6
 
7
7
  module Istox
8
8
  # Your code goes here...
9
9
  class Test
10
10
  def self.method1
11
- 'abc'
11
+ "abc"
12
12
  end
13
13
  end
14
14
 
15
- require 'istox/interfaces/chainhub/transaction'
16
- require 'istox/helpers/publisher'
17
- require 'istox/helpers/bunny_boot'
18
- require 'istox/helpers/vault'
19
- require 'istox/helpers/order_book'
20
- require 'istox/helpers/grpc_client'
21
- require 'istox/helpers/graphql_client'
22
- require 'istox/helpers/gruf_listener_hook'
23
- require 'istox/helpers/message_service'
24
- require 'istox/helpers/blockchain_service'
25
- require 'istox/helpers/f_math'
26
- require 'istox/helpers/my_open_struct'
27
- require 'istox/helpers/common_helper'
28
- require 'istox/models/blockchain_receipt'
29
- require 'istox/models/concerns/blockchain_receipt_query'
30
- require 'istox/consumers/blockchain_status_handler'
31
- require 'istox/migrations/create_blockchain_receipts'
32
- require 'istox/logging/hash_logging'
33
- require 'istox/logging/log_formatter'
15
+ require "istox/interfaces/chainhub/transaction"
16
+ require "istox/helpers/publisher"
17
+ require "istox/helpers/bunny_boot"
18
+ require "istox/helpers/vault"
19
+ require "istox/helpers/order_book"
20
+ require "istox/helpers/grpc_client"
21
+ require "istox/helpers/graphql_client"
22
+ require "istox/helpers/gruf_listener_hook"
23
+ require "istox/helpers/message_service"
24
+ require "istox/helpers/blockchain_receipt_service"
25
+ require "istox/helpers/f_math"
26
+ require "istox/models/blockchain_receipt"
27
+ require "istox/models/concerns/blockchain_receipt_query"
28
+ require "istox/consumers/blockchain_status_handler"
29
+ require "istox/consumers/blockchain_hash_handler"
30
+ require "istox/migrations/create_blockchain_receipts"
31
+ require "istox/logging/hash_logging"
32
+ require "istox/logging/log_formatter"
34
33
  require "istox/quant/bond"
35
34
  end
@@ -0,0 +1,19 @@
1
+ module Istox
2
+ class BlockchainHashHandler
3
+ class << self
4
+ def hash_generated(data, payload_target)
5
+ receipt = ::Istox::BlockchainReceipt.where(txid: data.uuid).first
6
+ if receipt.nil?
7
+ puts 'Transaction doesnt belong here, skipping...'
8
+ return
9
+ end
10
+
11
+ # sid cannot be nil
12
+ update_receipt = ::Istox::BlockchainReceipt.where(txid: data.uuid, txhash: nil).where.not(sid: nil).first
13
+ raise "Unable to find receipt to update" if update_receipt.blank?
14
+
15
+ update_receipt.update!(txhash: data.txnHash)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -1,54 +1,105 @@
1
1
  module Istox
2
2
  class BlockchainStatusHandler
3
3
  class << self
4
- # format of transaction
5
- # {
6
- # type: 'CHAINHUB_RESPONSE_EVENT',
7
- # uuid:'123', //original request uuid sent from backend
8
- # success:true, //status of the whole request in true/false
9
- # message:'', //In case of error, the message contain the error reason
10
- # txnCount:1, //Number of blockchain transactions from the original request
11
- # txnHashes:[] //Hashes for all transactions that has been submitted and mined by the blockchain for verification purpose
12
- # }
13
-
14
- def chainhub_response_event(transaction)
15
- receipt = ::Istox::BlockchainReceipt.where(txid: transaction.uuid).first
16
- if receipt.blank?
17
- puts 'Transaction doesn\'t belong to this backend, skipping...'
18
- return
19
- end
20
4
 
21
- status = transaction.success ? 'confirmed' : 'failed'
5
+ def txn_data_confirmed(transactions)
6
+ found_txns = transactions.map do |transaction|
7
+ receipt = ::Istox::BlockchainReceipt.where(txid: transaction.uuid).first
8
+ if !receipt.blank?
9
+ handling_receipt = ::Istox::BlockchainReceipt.where(txhash: transaction.id, txid: transaction.uuid).first
10
+ raise 'Unable to find receipt' if handling_receipt.blank?
11
+ transaction
12
+ else
13
+ puts 'Transaction doesnt belong here, skipping...'
14
+ nil
15
+ end
16
+ end.compact
17
+
18
+ found_txns.each do |transaction|
19
+ receipt = ::Istox::BlockchainReceipt.where(txhash: transaction.id, txid: transaction.uuid).first
20
+
21
+ receipt.update!(status: "confirmed")
22
+
23
+ resource = begin
24
+ class_eval("::#{receipt.resource_name}").find(receipt.resource_id)
25
+ rescue => e
26
+ puts "Class not found, skipping..."
27
+ next
28
+ end
29
+
30
+ receipt_list = get_receipt_list(resource)
31
+
32
+ next if resource_handled?(receipt_list)
22
33
 
23
- receipt.update!(status: status, message: transaction.message,
24
- txhash: transaction.txnHashes.present? ? transaction.txnHashes.join(',') : nil)
34
+ next if resource.outcome == 'pending'
35
+
36
+ if resource.outcome == 'confirmed'
37
+ resource.handle_confirm(receipt.resource_action)
38
+
39
+ mark_resource_handled(receipt_list)
40
+ publish_to_frontend(resource, true, receipt, receipt.sid, receipt_list)
41
+ end
25
42
 
26
- resource = begin
27
- class_eval("::#{receipt.resource_name}", __FILE__, __LINE__).find(receipt.resource_id)
28
- rescue StandardError
29
- puts 'Class not found, skipping...'
30
- return
31
43
  end
44
+ end
45
+
46
+ def txn_status_changed(transactions, payload_target)
47
+ # pre check all transaction does exists
48
+ found_txns = transactions.map do |transaction|
49
+ receipt = ::Istox::BlockchainReceipt.where(txid: transaction.uuid).first
50
+ if !receipt.blank?
51
+ handling_receipt = ::Istox::BlockchainReceipt.where(txhash: transaction.id, txid: transaction.uuid).first
52
+ raise 'Unable to find receipt' if handling_receipt.blank?
53
+ transaction
54
+ else
55
+ puts 'Transaction doesnt belong here, skipping...'
56
+ nil
57
+ end
58
+ end.compact
59
+
60
+ found_txns.each do |transaction|
61
+ receipt = ::Istox::BlockchainReceipt.where(txhash: transaction.id, txid: transaction.uuid).first
62
+
63
+ next if !(%w[failed pending].include?(transaction.status))
64
+ receipt.update!(status: transaction.status)
65
+
66
+ resource = begin
67
+ class_eval("::#{receipt.resource_name}").find(receipt.resource_id)
68
+ rescue => e
69
+ puts "Class not found, skipping..."
70
+ next
71
+ end
32
72
 
33
- return if resource_handled?(receipt)
73
+ receipt_list = get_receipt_list(resource)
34
74
 
35
- if status == 'confirmed'
36
- resource.handle_confirm(receipt)
75
+ next if resource_handled?(receipt_list)
37
76
 
38
- mark_resource_handled(receipt)
39
- publish_to_frontend(resource, true, receipt, receipt.sid)
77
+ # if transaction.status == 'confirmed'
78
+ # next if resource.outcome == 'pending'
40
79
 
41
- elsif status == 'failed'
42
- resource.handle_fail(receipt)
80
+ # if resource.outcome == 'confirmed'
81
+ # resource.handle_confirm(receipt.resource_action)
82
+
83
+ # mark_resource_handled(receipt_list)
84
+ # publish_to_frontend(resource, true, receipt, receipt.sid, receipt_list)
85
+ # end
86
+ # end
87
+
88
+ if transaction.status == 'failed'
89
+ resource.handle_fail(receipt.resource_action)
90
+
91
+ mark_resource_handled(receipt_list)
92
+ publish_to_frontend(resource, false, receipt, receipt.sid, receipt_list)
93
+ end
43
94
 
44
- mark_resource_handled(receipt)
45
- publish_to_frontend(resource, false, receipt, receipt.sid)
46
95
  end
47
96
  end
48
97
 
49
98
  private
50
99
 
51
- def publish_to_frontend(model, success, receipt, sid)
100
+ def publish_to_frontend(model, success, receipt, sid, receipt_list)
101
+ yield if block_given?
102
+
52
103
  ::Istox::Publisher.publish(
53
104
  'amq.topic',
54
105
  model.class.name.gsub('::', '').underscore.to_s,
@@ -64,26 +115,34 @@ module Istox
64
115
  data: {
65
116
  success: success,
66
117
  purpose: receipt.activity,
67
- message: receipt.message
118
+ txids: get_receipts_tx_hashes(receipt_list)
68
119
  }
69
120
  )
70
- rescue StandardError => e
71
- Rails.logger.error "Unable to publish to frontend for receipt #{receipt.inspect},
72
- but will silently ignore the error"
73
- Rails.logger.error e
74
121
  end
75
122
 
76
- def mark_resource_handled(receipt)
77
- receipt.update(resource_handled: true)
78
- rescue StandardError => e
79
- Rails.logger.error "Unable to update resource_handled for receipt #{receipt.inspect},
80
- but will silently ignore the error"
81
- Rails.logger.error e
123
+ def get_receipts_tx_hashes(receipt_list)
124
+ tx_hashes = receipt_list.map(&:txhash).compact
125
+
126
+ tx_hashes.join(', ')
82
127
  end
83
128
 
84
- def resource_handled?(receipt)
85
- receipt.resource_handled == true
129
+ def mark_resource_handled(receipt_list)
130
+ receipt_list.each do |receipt|
131
+ receipt.update(resource_handled: true)
132
+ end
86
133
  end
134
+
135
+ def resource_handled?(receipt_list)
136
+ receipt_list.map(&:resource_handled).none? { |item| item.nil? || item == false }
137
+ end
138
+
139
+ def get_receipt_list(resource)
140
+ ::Istox::BlockchainReceipt.where(
141
+ resource_name: resource.class.name,
142
+ resource_id: resource.id
143
+ )
144
+ end
145
+
87
146
  end
88
147
  end
89
148
  end
@@ -0,0 +1,71 @@
1
+ module Istox
2
+ class BlockchainReceiptService
3
+
4
+ def self.init(blockchain_receipt_klass)
5
+ @@blockchain_receipt_klass = blockchain_receipt_klass
6
+ end
7
+
8
+ def self.get_blockchain_receipt_klass
9
+ @@blockchain_receipt_klass
10
+ end
11
+
12
+ def self.generate_uuid
13
+ klass = ::Istox::BlockchainReceiptService.blockchain_receipt_class
14
+ uuid = SecureRandom.uuid
15
+
16
+ klass.create!({
17
+ txid: uuid
18
+ })
19
+
20
+ uuid
21
+ end
22
+
23
+ def create!(tx_message, model, sid, action, is_request: false)
24
+ klass = ::Istox::BlockchainReceiptService.blockchain_receipt_class
25
+
26
+ # delete the previous existing blockchain receipts
27
+ klass.where(resource_name: model.class.name,
28
+ resource_id: model.id).destroy_all
29
+
30
+ (0...tx_message.txnCount).each do |i|
31
+ if i == 0
32
+ blockchain_receipt = klass.find_by_txid(tx_message.uuid)
33
+
34
+ raise "Unable to find blockchain receipt with uuid #{tx_message.uuid}, have you forgetten to generate uuid?" if blockchain_receipt.blank?
35
+
36
+ blockchain_receipt.update!({
37
+ sid: sid,
38
+ txid: tx_message.uuid,
39
+ resource_name: model.class.name,
40
+ resource_id: model.id,
41
+ resource_action: action,
42
+ is_request: is_request
43
+ })
44
+ else
45
+ blockchain_receipt = klass.new(
46
+ sid: sid,
47
+ txid: tx_message.uuid,
48
+ resource_name: model.class.name,
49
+ resource_id: model.id,
50
+ resource_action: action,
51
+ is_request: is_request
52
+ )
53
+ blockchain_receipt.save!
54
+ end
55
+ end
56
+ end
57
+
58
+ def self.blockchain_receipt_class
59
+ raise "Have you forgetten to init blockchain receipt service?" if ::Istox::BlockchainReceiptService.get_blockchain_receipt_klass == nil
60
+
61
+ blockchain_receipt_klass = ::Istox::BlockchainReceiptService.get_blockchain_receipt_klass
62
+ klass = class_eval("::#{blockchain_receipt_klass.name}")
63
+ unless klass <= ::Istox::BlockchainReceipt
64
+ raise RuntimeError, "#{blockchain_receipt_klass.name} does not inherit istox blockchain receipt"
65
+ end
66
+
67
+ return klass
68
+ end
69
+
70
+ end
71
+ end
@@ -1,7 +1,7 @@
1
- # rubocop:disable Naming/UncommunicativeMethodParamName
2
1
  module Istox
3
2
  class FMath
4
3
  class << self
4
+
5
5
  def add(x, y)
6
6
  BigDecimal.mode(BigDecimal::ROUND_MODE, :down)
7
7
 
@@ -11,7 +11,7 @@ module Istox
11
11
  x = ::BigDecimal.new(x.to_s)
12
12
  y = ::BigDecimal.new(y.to_s)
13
13
 
14
- x.add(y, 100).truncate(18).to_s
14
+ return x.add(y, 100).truncate(18).to_s
15
15
  end
16
16
 
17
17
  def sub(x, y)
@@ -23,7 +23,7 @@ module Istox
23
23
  x = ::BigDecimal.new(x.to_s)
24
24
  y = ::BigDecimal.new(y.to_s)
25
25
 
26
- x.sub(y, 100).truncate(18).to_s
26
+ return x.sub(y, 100).truncate(18).to_s
27
27
  end
28
28
 
29
29
  def mul(x, y)
@@ -35,7 +35,7 @@ module Istox
35
35
  x = ::BigDecimal.new(x.to_s)
36
36
  y = ::BigDecimal.new(y.to_s)
37
37
 
38
- x.mult(y, 100).truncate(18).to_s
38
+ return x.mult(y, 100).truncate(18).to_s
39
39
  end
40
40
 
41
41
  def div(x, y)
@@ -47,17 +47,19 @@ module Istox
47
47
  x = to_fixed(x)
48
48
  y = to_fixed(y)
49
49
 
50
- return ::BigDecimal.new('1').to_s if x == y
51
-
52
- fixed1 = ::BigDecimal.new('1e18')
50
+ return ::BigDecimal.new("1").to_s if x == y
53
51
 
54
- return from_fixed(x.div(y, 100).mult(fixed1, 100)).to_s if x.div(y, 100).modulo(BigDecimal.new(10)).zero? && x.modulo(y).zero?
52
+ fixed_1 = ::BigDecimal.new("1e18")
53
+
54
+ if (((x.div(y, 100)).modulo(BigDecimal.new(10)) == 0) && (x.modulo(y) == 0))
55
+ return from_fixed((x.div(y, 100).mult(fixed_1, 100)))
56
+ end
55
57
 
56
- r_y = fixed1.mult(fixed1, 100).truncate(0).div(y, 100).truncate(0)
58
+ r_y = fixed_1.mult(fixed_1, 100).truncate(0).div(y, 100).truncate(0)
57
59
 
58
- result = from_fixed(x.mult(r_y, 100).truncate(0).div(fixed1, 100).truncate(0))
60
+ result = from_fixed(x.mult(r_y, 100).truncate(0).div(fixed_1, 100).truncate(0))
59
61
 
60
- result.truncate(18).to_s
62
+ return result.truncate(18).to_s
61
63
  end
62
64
 
63
65
  def round_up(x, digits)
@@ -65,23 +67,24 @@ module Istox
65
67
  x = 0 if x.blank?
66
68
  ::BigDecimal.new(x.to_s).round(digits).to_s
67
69
  end
68
-
70
+
69
71
  def round_down(x, digits)
70
72
  BigDecimal.mode(BigDecimal::ROUND_MODE, :down)
71
73
  x = 0 if x.blank?
72
74
  ::BigDecimal.new(x.to_s).round(digits).to_s
73
75
  end
74
76
 
75
- private
77
+ private
76
78
 
77
79
  def to_fixed(x)
78
- ::BigDecimal.new(x.to_s).mult(::BigDecimal.new('1e18'), 100).truncate(18)
80
+ return ::BigDecimal.new(x.to_s).mult(::BigDecimal.new('1e18'), 100).truncate(18)
79
81
  end
80
82
 
81
83
  def from_fixed(x)
82
- ::BigDecimal.new(x.to_s).div(::BigDecimal.new('1e18'), 100).truncate(18)
84
+ return ::BigDecimal.new(x.to_s).div(::BigDecimal.new('1e18'), 100).truncate(18)
83
85
  end
86
+
87
+
84
88
  end
85
89
  end
86
90
  end
87
- # rubocop:enable Naming/UncommunicativeMethodParamName
@@ -1,35 +1,35 @@
1
- require 'graphlient'
1
+ require "graphlient"
2
2
 
3
3
  module Istox
4
4
  class GraphqlClient
5
- class << self
6
- def add_host(host_type, url)
7
- @@hosts = {} unless defined?(@@hosts)
8
- init_host(host_type, url)
9
- end
10
-
11
- def query(host_type, query, variables = {})
12
- client = @@hosts[host_type]
13
-
14
- raise "Please make sure you have initialised graphql cient for host #{host_type}" unless client
15
-
16
- Rails.logger.info "Querying Graphql host: #{host_type}, query: #{query}, variables: #{variables.inspect}"
17
- result = client.query(query, variables)
18
-
19
- return_values = ::Istox::CommonHelper.to_open_struct(result&.data)
20
-
21
- Rails.logger.info "Graphql result: #{return_values.inspect}"
22
-
23
- return_values
24
- end
25
-
26
- private
27
-
28
- def init_host(host_type, url)
29
- client = Graphlient::Client.new(url, http: Graphlient::Adapters::HTTP::HTTPAdapter)
5
+ class << self
6
+ def add_host(host_type, url)
7
+ unless defined?(@@hosts)
8
+ @@hosts = {}
9
+ end
10
+ init_host(host_type, url)
11
+ end
12
+
13
+ def query(host_type, query, variables = {})
14
+ client = @@hosts[host_type]
15
+
16
+ raise "Please make sure you have initialised graphql cient for host #{host_type}" if !client
17
+
18
+ Rails.logger.info "Querying Graphql host: #{host_type}, query: #{query}, variables: #{variables.inspect}"
19
+ result = client.query(query, variables)
20
+ Rails.logger.info "Graphql result: #{result.inspect}"
21
+
22
+ return result
23
+ end
24
+
25
+ private
26
+
27
+ def init_host(host_type, url)
28
+ client = Graphlient::Client.new(url, http: Graphlient::Adapters::HTTP::HTTPAdapter)
29
+
30
+ @@hosts[host_type] = client
31
+ end
30
32
 
31
- @@hosts[host_type] = client
32
33
  end
33
- end
34
34
  end
35
- end
35
+ end
@@ -1,63 +1,66 @@
1
1
  module Istox
2
- class GrpcClient
3
- class << self
4
- def add_host(host_type, url)
5
- @@hosts = {} unless defined?(@@hosts)
2
+ class GrpcClient
3
+ class << self
4
+ def add_host(host_type, url)
5
+ unless defined?(@@hosts)
6
+ @@hosts = {}
7
+ end
6
8
 
7
- @@hosts[host_type] = url
8
- end
9
+ @@hosts[host_type] = url
10
+ end
9
11
 
10
- def call(host_type, service, method, **keyword_args)
11
- execute(host_type, service, method, **keyword_args)
12
- # rescue => e
13
- # reinitiate service and try again, second chance
14
- # reinitiate_service(host_type, service)
15
- # execute(host_type, service, method, **keyword_args)
16
- end
12
+ def call(host_type, service, method, **keyword_args)
13
+ execute(host_type, service, method, **keyword_args)
14
+ # rescue => e
15
+ # reinitiate service and try again, second chance
16
+ # reinitiate_service(host_type, service)
17
+ # execute(host_type, service, method, **keyword_args)
18
+ end
19
+
20
+ private
17
21
 
18
- private
22
+ def execute(host_type, service, method, **keyword_args)
23
+ Rails.logger.info "Calling method in grpc method: #{method.inspect}, params: #{keyword_args.inspect}"
24
+ t1 = Time.now
25
+
26
+ result = get_host(host_type, service).call(method, keyword_args)
27
+ Rails.logger.info "Time taken for grpc execution: #{Time.now - t1} seconds"
28
+ Rails.logger.info "Result: #{result.message.inspect}"
29
+ result
30
+ end
19
31
 
20
- def execute(host_type, service, method, **keyword_args)
21
- Rails.logger.info "Calling method in grpc method: #{method.inspect}, params: #{keyword_args.inspect}"
22
- t1 = Time.now
32
+ def get_host(host_type, service)
33
+ unless defined?(@@services)
34
+ @@services = {}
35
+ end
23
36
 
24
- result = get_host(host_type, service).call(method, keyword_args)
25
- Rails.logger.info "Time taken for grpc execution: #{Time.now - t1} seconds"
37
+ grpc_client = @@services[get_key(host_type, service)]
26
38
 
27
- return_values = ::Istox::CommonHelper.to_open_struct(result.message)
28
- Rails.logger.info "Result: #{return_values}"
39
+ if grpc_client
40
+ return grpc_client
41
+ else
42
+ reinitiate_service(host_type, service)
43
+ return @@services[get_key(host_type, service)]
44
+ end
45
+ end
29
46
 
30
- return_values
31
- end
47
+ def reinitiate_service(host_type, service)
48
+ unless defined?(@@services)
49
+ @@services = {}
50
+ end
32
51
 
33
- def get_host(host_type, service)
34
- @@services = {} unless defined?(@@services)
52
+ host_url = @@hosts[host_type]
53
+ raise StandardError, 'Unable to find host, have you forgotten to add host to grpc client?' if !host_url
54
+
55
+ Rails.logger.info 'Reinitiating to grpc host at ' + host_url
56
+ t1 = Time.now
57
+ @@services[get_key(host_type, service)] = ::Gruf::Client.new(service: service, options: { hostname: host_url })
58
+ Rails.logger.info "Time taken for reinitiating grpc host: #{Time.now - t1} seconds"
59
+ end
35
60
 
36
- grpc_client = @@services[get_key(host_type, service)]
37
-
38
- if grpc_client
39
- return grpc_client
40
- else
41
- reinitiate_service(host_type, service)
42
- return @@services[get_key(host_type, service)]
61
+ def get_key(host_type, service)
62
+ host_type.to_s + service.to_s
63
+ end
43
64
  end
44
- end
45
-
46
- def reinitiate_service(host_type, service)
47
- @@services = {} unless defined?(@@services)
48
-
49
- host_url = @@hosts[host_type]
50
- raise StandardError, 'Unable to find host, have you forgotten to add host to grpc client?' unless host_url
51
-
52
- Rails.logger.info 'Reinitiating to grpc host at ' + host_url
53
- t1 = Time.now
54
- @@services[get_key(host_type, service)] = ::Gruf::Client.new(service: service, options: { hostname: host_url })
55
- Rails.logger.info "Time taken for reinitiating grpc host: #{Time.now - t1} seconds"
56
- end
57
-
58
- def get_key(host_type, service)
59
- host_type.to_s + service.to_s
60
- end
61
65
  end
62
- end
63
- end
66
+ end
@@ -2,6 +2,7 @@ module Istox
2
2
  class OrderBook
3
3
  class << self
4
4
  def allocation(soft_cap, total_supply, investments)
5
+
5
6
  # sort by token price desc, and id asc
6
7
  investments = investments.sort do |a, b|
7
8
  [b[:token_price], a[:id]] <=> [a[:token_price], b[:id]]
@@ -10,79 +11,50 @@ module Istox
10
11
  total_supply = ::BigDecimal.new(total_supply.to_s)
11
12
 
12
13
  interests = investments
13
- cutoff_price = 0.0
14
- total_bid_token = 0.0
15
- total_allocated = 0.0
16
- total_unallocated = 0.0
17
- total_investment = 0.0
18
- cutoff_price = ::Istox::FMath.round_up(::Istox::FMath.div(soft_cap, total_supply), 2)
19
- is_cutoff = false
14
+ if interests.count > 0
15
+ cutoff_price = 0.0
16
+ total_bid_token = 0.0
17
+ total_allocated = 0.0
18
+ total_unallocated = 0.0
19
+ total_investment = 0.0
20
+ cutoff_price = ::Istox::FMath.round_down(::Istox::FMath.div(soft_cap, total_supply), 2)
21
+ is_cutoff = false
20
22
 
21
- # return result immediately if no interest
22
- unless interests.count.positive?
23
- return { total_supply: total_supply.to_s, total_investment: '0',
24
- cutoff_price: cutoff_price, total_bid_token: '0',
25
- total_allocated: '0', total_unallocated: total_supply.to_s,
26
- interests: [] }
27
- end
28
-
29
- interests = interests.map do |item|
30
- bid_token = ::Istox::FMath.div(item[:fiat_amount], item[:token_price])
31
- total_bid_token = ::Istox::FMath.add(total_bid_token, bid_token)
32
- allocated = 0.0
33
- unallocated = bid_token
34
- unless is_cutoff
35
- allocated = bid_token
36
- unallocated = 0.0
37
- if ::BigDecimal.new(::Istox::FMath.add(total_allocated, bid_token)) >= total_supply
38
- unallocated = ::Istox::FMath.sub(::Istox::FMath.add(total_allocated, bid_token), total_supply)
39
- allocated = ::Istox::FMath.sub(bid_token, unallocated)
40
- cutoff_price = item[:token_price]
41
- is_cutoff = true
23
+ interests = interests.map do |item|
24
+ bid_token = ::Istox::FMath.div(item[:fiat_amount], item[:token_price])
25
+ total_bid_token = ::Istox::FMath.add(total_bid_token, bid_token)
26
+ allocated = 0.0
27
+ unallocated = bid_token
28
+ unless is_cutoff
29
+ allocated = bid_token
30
+ unallocated = 0.0
31
+ if ::BigDecimal.new(::Istox::FMath.add(total_allocated, bid_token)) >= total_supply
32
+ unallocated = ::Istox::FMath.sub(::Istox::FMath.add(total_allocated, bid_token), total_supply)
33
+ allocated = ::Istox::FMath.sub(bid_token, unallocated)
34
+ cutoff_price = item[:token_price]
35
+ is_cutoff = true
36
+ end
37
+ total_allocated = ::Istox::FMath.add(total_allocated, allocated)
38
+ total_unallocated = ::Istox::FMath.add(total_unallocated, unallocated)
42
39
  end
43
- total_allocated = ::Istox::FMath.add(total_allocated, allocated)
44
- total_unallocated = ::Istox::FMath.add(total_unallocated, unallocated)
40
+ { id: item[:id], fiat_amount: item[:fiat_amount], bid_price: item[:token_price], bid_token: bid_token,
41
+ allocated: allocated, unallocated: unallocated }
45
42
  end
46
- {
47
- id: item[:id],
48
- # user bidding total fiat amount
49
- fiat_amount: item[:fiat_amount],
50
- # user bidding price
51
- bid_price: item[:token_price],
52
- # total user bidding token derived from fiat_amount / token_price
53
- bid_token: bid_token,
54
- # round down allocated token to whole number
55
- allocated: ::Istox::FMath.round_down(allocated, 0),
56
- # round up unallocated token to whole number
57
- unallocated: ::Istox::FMath.round_up(unallocated, 0)
58
- }
59
- end
60
43
 
61
- interests = interests.map do |item|
62
- investment = ::Istox::FMath.mul(item[:allocated], cutoff_price)
63
- total_investment = ::Istox::FMath.add(total_investment, investment)
64
-
65
- # each user maximum total investment amount in fiat
66
- item.merge!(investment: investment)
44
+ interests = interests.map do |item|
45
+ investment = ::Istox::FMath.mul(item[:allocated], cutoff_price)
46
+ total_investment = ::Istox::FMath.add(total_investment, investment)
47
+ item.merge!(investment: investment)
48
+ end
49
+
50
+ return { total_supply: total_supply, total_investment: total_investment,
51
+ cutoff_price: cutoff_price, total_bid_token: total_bid_token,
52
+ total_allocated: total_allocated, total_unallocated: total_unallocated,
53
+ interests: interests }
54
+ else
55
+ raise 'Registration interest is empty'
67
56
  end
68
-
69
- {
70
- # total token supply
71
- total_supply: total_supply.to_s,
72
- # total investment in fiat
73
- total_investment: total_investment,
74
- # cut off price
75
- cutoff_price: cutoff_price.to_s,
76
- # total bid tokens, more than total supply for oversubscribe case
77
- total_bid_token: total_bid_token,
78
- # total allocated tokens
79
- total_allocated: total_allocated,
80
- # total unallocated tokens
81
- total_unallocated: total_unallocated,
82
- # all investor interest results
83
- interests: interests
84
- }
85
57
  end
86
58
  end
87
59
  end
88
- end
60
+ end
@@ -13,8 +13,9 @@ module Istox
13
13
  include ActiveSupport::TaggedLogging::Formatter
14
14
 
15
15
  def call(severity, timestamp, progname, msg)
16
- tagged_message = if msg.is_a?(Hash) then tags_text.present? ? msg.merge(tags: tags_text) : msg
17
- elsif tags_text.present? then { message: msg, tag: tags_text }
16
+ tagged_message = case
17
+ when msg.is_a?(Hash) then tags_text.present? ? msg.merge(tags: tags_text) : msg
18
+ when tags_text.present? then { message: msg, tag: tags_text }
18
19
  else msg
19
20
  end
20
21
 
@@ -1,9 +1,8 @@
1
1
  # frozen_string_literal: true
2
-
3
2
  module Istox
4
3
  module Logging
5
4
  class LogFormatter
6
- def call(severity, _time, progname, msg = '')
5
+ def call(severity, time, progname, msg='')
7
6
  return '' if msg.blank?
8
7
 
9
8
  hash = {
@@ -11,9 +10,11 @@ module Istox
11
10
  message: processed_message(msg)
12
11
  }
13
12
 
14
- hash[:app] = progname if progname.present?
13
+ if progname.present?
14
+ hash[:app] = progname
15
+ end
15
16
 
16
- hash.to_json + "\n"
17
+ return hash.to_json + "\n"
17
18
 
18
19
  # return "timestamp='#{time}' level=#{severity} progname='#{progname}' #{processed_message(msg)}\n" if progname.present?
19
20
  # "timestamp='#{time}' level=#{severity} #{processed_message(msg)}\n"
@@ -1,26 +1,27 @@
1
1
  module Istox
2
- class CreateBlockchainReceipts < ActiveRecord::Migration[5.0]
3
- def initialize(_, _, table_name = nil)
4
- @table_name = table_name
5
- @table_name ||= :blockchain_receipts
6
- end
2
+ class CreateBlockchainReceipts < ActiveRecord::Migration[5.0]
3
+ def initialize(_, _, table_name = nil)
4
+ @table_name = table_name
5
+ unless @table_name
6
+ @table_name = :blockchain_receipts
7
+ end
8
+ end
7
9
 
8
- def change
9
- create_table @table_name do |t|
10
- t.string :txid
11
- t.string :txhash
12
- t.integer :resource_id
13
- t.string :resource_action
14
- t.string :resource_name
15
- t.boolean :resource_handled
16
- t.datetime :deleted_at, index: true
17
- t.timestamps
18
- t.string :sid
19
- t.string :status, default: 'pending'
20
- t.text :message
21
- t.boolean :is_request, default: false
22
- t.integer :lock_version
23
- end
10
+ def change
11
+ create_table @table_name do |t|
12
+ t.string :txid
13
+ t.string :txhash
14
+ t.integer :resource_id
15
+ t.string :resource_action
16
+ t.string :resource_name
17
+ t.boolean :resource_handled
18
+ t.datetime :deleted_at, index: true
19
+ t.timestamps
20
+ t.string :sid
21
+ t.string :status, :default => "pending"
22
+ t.boolean :is_request, :default => false
23
+ t.integer :lock_version
24
+ end
25
+ end
24
26
  end
25
- end
26
- end
27
+ end
@@ -2,8 +2,11 @@ module Istox
2
2
  class BlockchainReceipt < ActiveRecord::Base
3
3
  acts_as_paranoid
4
4
 
5
+
5
6
  def activity
6
- I18n.t("#{resource_name}.#{resource_action}") if resource_name.present? && resource_action.present?
7
+ if resource_name.present? && resource_action.present?
8
+ I18n.t("#{resource_name}.#{resource_action}")
9
+ end
7
10
  end
8
11
  end
9
- end
12
+ end
@@ -1,31 +1,45 @@
1
1
  module Istox
2
2
  module BlockchainReceiptQuery
3
3
  extend ActiveSupport::Concern
4
-
5
- # overrideable, when blockchain transaction has confirmed
6
- def handle_confirm(_receipt)
4
+
5
+ #overrideable, when blockchain transaction has confirmed
6
+ def handle_confirm(resource_action)
7
7
  self
8
8
  end
9
9
 
10
- # overrideable, when blockchain transaction has failed
11
- def handle_fail(_receipt)
10
+ #overrideable, when blockchain transaction has failed
11
+ def handle_fail(resource_action)
12
12
  self
13
13
  end
14
14
 
15
- # overrideable, extra data that will be published back to frontend
15
+ #overrideable, extra data that will be published back to frontend
16
16
  def handle_extra
17
17
  nil
18
18
  end
19
19
 
20
20
  # outcome of the blockchain transaction, can be "pending" / "confirmed" / "failed"
21
21
  def outcome
22
- blockchain_receipt = ::Istox::BlockchainReceipt.where(resource_id: id, resource_name: self.class.name).first
22
+ blockchain_receipts = get_blockchain_receipts
23
+
24
+ return "confirmed" if blockchain_receipts.empty?
25
+
26
+ # return failed state if there is any failed hashes
27
+ return "failed" if blockchain_receipts.any?{ |r| r.status == 'failed' }
23
28
 
24
- return 'confirmed' unless blockchain_receipt.present?
29
+ # return pending state if there is any pending hashes
30
+ return "pending" if blockchain_receipts.any?{ |r| r.status == 'pending' }
25
31
 
26
- return 'confirmed' if blockchain_receipt.status.blank?
32
+ # return confirmed otherwise
33
+ return "confirmed"
34
+ end
35
+
36
+ def get_blockchain_receipts
37
+ ::Istox::BlockchainReceipt.where(resource_id: self.id, resource_name: self.class.name).all
38
+ end
27
39
 
28
- blockchain_receipt.status
40
+ def last_receipt
41
+ ::Istox::BlockchainReceipt.where(resource_id: self.id, resource_name: self.class.name).last
29
42
  end
43
+
30
44
  end
31
45
  end
@@ -1,3 +1,3 @@
1
1
  module Istox
2
- VERSION = '0.1.81-test10'.freeze
2
+ VERSION = "0.1.81"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: istox
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.81.pre.test10
4
+ version: 0.1.81
5
5
  platform: ruby
6
6
  authors:
7
7
  - Siong Leng
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-09-15 00:00:00.000000000 Z
11
+ date: 2019-09-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bunny
@@ -278,8 +278,6 @@ files:
278
278
  - ".idea/modules.xml"
279
279
  - ".idea/vcs.xml"
280
280
  - ".idea/workspace.xml"
281
- - ".rubocop.yml"
282
- - ".solargraph.yml"
283
281
  - CODE_OF_CONDUCT.md
284
282
  - Gemfile
285
283
  - Gemfile.lock
@@ -289,16 +287,15 @@ files:
289
287
  - bin/setup
290
288
  - istox.gemspec
291
289
  - lib/istox.rb
290
+ - lib/istox/consumers/blockchain_hash_handler.rb
292
291
  - lib/istox/consumers/blockchain_status_handler.rb
293
- - lib/istox/helpers/blockchain_service.rb
292
+ - lib/istox/helpers/blockchain_receipt_service.rb
294
293
  - lib/istox/helpers/bunny_boot.rb
295
- - lib/istox/helpers/common_helper.rb
296
294
  - lib/istox/helpers/f_math.rb
297
295
  - lib/istox/helpers/graphql_client.rb
298
296
  - lib/istox/helpers/grpc_client.rb
299
297
  - lib/istox/helpers/gruf_listener_hook.rb
300
298
  - lib/istox/helpers/message_service.rb
301
- - lib/istox/helpers/my_open_struct.rb
302
299
  - lib/istox/helpers/order_book.rb
303
300
  - lib/istox/helpers/publisher.rb
304
301
  - lib/istox/helpers/vault.rb
@@ -324,9 +321,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
324
321
  version: '0'
325
322
  required_rubygems_version: !ruby/object:Gem::Requirement
326
323
  requirements:
327
- - - ">"
324
+ - - ">="
328
325
  - !ruby/object:Gem::Version
329
- version: 1.3.1
326
+ version: '0'
330
327
  requirements: []
331
328
  rubygems_version: 3.0.6
332
329
  signing_key:
@@ -1,102 +0,0 @@
1
- require: rubocop-rspec
2
-
3
- AllCops:
4
- TargetRubyVersion: 2.5
5
- Exclude:
6
- - .gems/**/*
7
- - bin/**/*
8
- - config/**/*
9
- - db/**/*
10
- - log/**/*
11
- - public/**/*
12
- - tmp/**/*
13
- - vendor/**/*
14
- - spec/rails_helper.rb
15
- - spec/spec_helper.rb
16
- - config.ru
17
- - Guardfile
18
- - Rakefile
19
-
20
- Documentation:
21
- Enabled: false
22
-
23
- Layout/SpaceBeforeFirstArg:
24
- Exclude:
25
- - app/views/api/**/**/*
26
-
27
- Lint/AmbiguousBlockAssociation:
28
- Exclude:
29
- - spec/**/*
30
-
31
- Metrics/AbcSize:
32
- # The ABC size is a calculated magnitude, so this number can be an Integer or
33
- # a Float.
34
- Max: 100
35
-
36
- Metrics/BlockLength:
37
- CountComments: false # count full line comments?
38
- Max: 25
39
- Exclude:
40
- - config/**/*
41
- - spec/**/*
42
- - app/admin/**/*
43
-
44
- Metrics/BlockNesting:
45
- Max: 4
46
-
47
- Metrics/ClassLength:
48
- CountComments: false # count full line comments?
49
- Max: 200
50
-
51
- # Avoid complex methods.
52
- Metrics/CyclomaticComplexity:
53
- Max: 20
54
-
55
- Metrics/MethodLength:
56
- CountComments: false # count full line comments?
57
- Max: 100
58
-
59
- Metrics/ModuleLength:
60
- CountComments: false # count full line comments?
61
- Max: 200
62
-
63
- Metrics/LineLength:
64
- Max: 130
65
- # To make it possible to copy or click on URIs in the code, we allow lines
66
- # containing a URI to be longer than Max.
67
- AllowURI: true
68
- URISchemes:
69
- - http
70
- - https
71
-
72
- Metrics/ParameterLists:
73
- Max: 5
74
- CountKeywordArgs: true
75
-
76
- Metrics/PerceivedComplexity:
77
- Max: 12
78
-
79
- Style/FrozenStringLiteralComment:
80
- Enabled: false
81
-
82
- Style/ModuleFunction:
83
- Enabled: false
84
-
85
- RSpec/MultipleExpectations:
86
- Max: 99
87
-
88
- RSpec/ExampleLength:
89
- Max: 100
90
-
91
- Lint/BigDecimalNew:
92
- Enabled: false
93
-
94
-
95
- RSpec/MessageSpies:
96
- Enabled: false
97
-
98
- RSpec/AnyInstance:
99
- Enabled: false
100
-
101
- RSpec/VerifiedDoubles:
102
- Enabled: false
@@ -1,14 +0,0 @@
1
- ---
2
- include:
3
- - "**/*.rb"
4
- exclude:
5
- - spec/**/*
6
- - test/**/*
7
- - vendor/**/*
8
- - ".bundle/**/*"
9
- require: []
10
- domains: []
11
- reporters:
12
- - rubocop
13
- require_paths: []
14
- max_files: 5000
@@ -1,64 +0,0 @@
1
- module Istox
2
- class BlockchainService
3
- def self.init(blockchain_receipt_klass)
4
- @@blockchain_receipt_klass = blockchain_receipt_klass
5
- end
6
-
7
- def self.get_blockchain_receipt_klass
8
- @@blockchain_receipt_klass
9
- end
10
-
11
- def self.request(sid:, action:, before:, execute:)
12
- start(sid: sid, action: action, before: before, execute: execute, is_request: true)
13
- end
14
-
15
- def self.run(sid:, action:, before:, execute:)
16
- start(sid: sid, action: action, before: before, execute: execute)
17
- end
18
- class << self
19
- private
20
-
21
- # before is the proc that will be executed before, must return the main model blockchain receipt will bind to
22
- def start(sid:, action:, before:, execute:, is_request: false)
23
- # create blockchain receipt first
24
- klass = blockchain_receipt_class
25
- uuid = ::SecureRandom.uuid
26
- @receipt = klass.create!(
27
- txid: uuid,
28
- sid: sid,
29
- is_request: is_request,
30
- resource_action: action
31
- )
32
-
33
- ::ActiveRecord::Base.transaction do
34
- # execute before proc, and get the model that blockchain receipt should bind to
35
- model = before.call(uuid)
36
-
37
- # delete the previous existing blockchain receipts
38
- klass.where(resource_name: model.class.name, resource_id: model.id).destroy_all
39
-
40
- # then update receipt
41
- @receipt.update!(resource_id: model.id, resource_name: model.class.name)
42
-
43
- # execute the actual call to chainhub
44
- execute.call(uuid)
45
- end
46
- rescue StandardError => e
47
- @receipt&.destroy
48
- raise e
49
- end
50
-
51
- def blockchain_receipt_class
52
- raise 'Have you forgetten to init blockchain receipt service?' if get_blockchain_receipt_klass.nil?
53
-
54
- blockchain_receipt_klass = get_blockchain_receipt_klass
55
- klass = class_eval("::#{blockchain_receipt_klass.name}", __FILE__, __LINE__)
56
- unless klass <= ::Istox::BlockchainReceipt
57
- raise "#{blockchain_receipt_klass.name} does not inherit istox blockchain receipt"
58
- end
59
-
60
- klass
61
- end
62
- end
63
- end
64
- end
@@ -1,45 +0,0 @@
1
- module Istox
2
- module CommonHelper
3
- def self.to_open_struct(model)
4
- return nil if model.blank?
5
-
6
- if model.is_a?(Array)
7
- model.map do |item|
8
- hash = deep_to_h(item).deep_transform_keys { |key| key.to_s.underscore.to_sym }
9
- to_recursive_ostruct(hash)
10
- end
11
- else
12
- hash = deep_to_h(model).deep_transform_keys { |key| key.to_s.underscore.to_sym }
13
- to_recursive_ostruct(hash)
14
- end
15
- end
16
-
17
- def self.to_recursive_ostruct(obj)
18
- if obj.is_a?(Hash)
19
- ::Istox::MyOpenStruct.new(obj.map { |key, val| [key, to_recursive_ostruct(val)] }.to_h)
20
- elsif obj.is_a?(Array)
21
- obj.map { |o| to_recursive_ostruct(o) }
22
- elsif obj.is_a?(OpenStruct)
23
- ::Istox::MyOpenStruct.new(obj)
24
- else # Assumed to be a primitive value
25
- obj
26
- end
27
- end
28
-
29
- def self.deep_to_h(obj)
30
- if obj.is_a?(Array)
31
- obj.map { |r| deep_to_h(r) }
32
- elsif obj.is_a?(OpenStruct) || obj.is_a?(Hash) || (obj.methods.include?(:to_h) && obj.present?)
33
- obj.to_h.transform_values do |v|
34
- if v.is_a?(OpenStruct) || v.is_a?(Array)
35
- deep_to_h(v)
36
- else
37
- v
38
- end
39
- end
40
- else
41
- obj
42
- end
43
- end
44
- end
45
- end
@@ -1,13 +0,0 @@
1
- module Istox
2
- class MyOpenStruct < OpenStruct
3
- def to_json(*_args)
4
- hash = ::Istox::CommonHelper.deep_to_h(self)
5
-
6
- hash.to_json
7
- end
8
-
9
- def to_hash
10
- ::Istox::CommonHelper.deep_to_h(self)
11
- end
12
- end
13
- end