istox 0.1.81.pre.test10 → 0.1.81

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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