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 +4 -4
- data/Gemfile.lock +1 -1
- data/lib/istox.rb +22 -23
- data/lib/istox/consumers/blockchain_hash_handler.rb +19 -0
- data/lib/istox/consumers/blockchain_status_handler.rb +106 -47
- data/lib/istox/helpers/blockchain_receipt_service.rb +71 -0
- data/lib/istox/helpers/f_math.rb +19 -16
- data/lib/istox/helpers/graphql_client.rb +29 -29
- data/lib/istox/helpers/grpc_client.rb +54 -51
- data/lib/istox/helpers/order_book.rb +40 -68
- data/lib/istox/logging/hash_logging.rb +3 -2
- data/lib/istox/logging/log_formatter.rb +5 -4
- data/lib/istox/migrations/create_blockchain_receipts.rb +24 -23
- data/lib/istox/models/blockchain_receipt.rb +5 -2
- data/lib/istox/models/concerns/blockchain_receipt_query.rb +24 -10
- data/lib/istox/version.rb +1 -1
- metadata +6 -9
- data/.rubocop.yml +0 -102
- data/.solargraph.yml +0 -14
- data/lib/istox/helpers/blockchain_service.rb +0 -64
- data/lib/istox/helpers/common_helper.rb +0 -45
- data/lib/istox/helpers/my_open_struct.rb +0 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b9b67e7deab7a2a53ab80d237842554f21ca126e3542bf75dfbbb68a46961395
|
4
|
+
data.tar.gz: 913e6213c402f933ac375bb77999119131d25e0a886c5cf2819c8ed56685ba88
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6c02663da343a9b5efef558084c5a14f32c92900b055d3fc3041e71dec38a1fa828b2e8ed4aee8ef7f1c2f7eccc991bd11a24bb2e7300505b6b11e025ff4249d
|
7
|
+
data.tar.gz: a57ed4210294057d2ef6cbbb9dedab41b28e0a2f78f8f75e2d97d17f5afce0b3a9948f9aca7ad0a8b0d685bfd58ebbf08d0876a0236b0833ff100beed7595368
|
data/Gemfile.lock
CHANGED
data/lib/istox.rb
CHANGED
@@ -1,35 +1,34 @@
|
|
1
1
|
require 'active_record'
|
2
2
|
require 'paranoia'
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
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
|
-
|
11
|
+
"abc"
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
-
require
|
16
|
-
require
|
17
|
-
require
|
18
|
-
require
|
19
|
-
require
|
20
|
-
require
|
21
|
-
require
|
22
|
-
require
|
23
|
-
require
|
24
|
-
require
|
25
|
-
require
|
26
|
-
require
|
27
|
-
require
|
28
|
-
require
|
29
|
-
require
|
30
|
-
require
|
31
|
-
require
|
32
|
-
require
|
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
|
-
|
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
|
-
|
24
|
-
|
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
|
-
|
73
|
+
receipt_list = get_receipt_list(resource)
|
34
74
|
|
35
|
-
|
36
|
-
resource.handle_confirm(receipt)
|
75
|
+
next if resource_handled?(receipt_list)
|
37
76
|
|
38
|
-
|
39
|
-
|
77
|
+
# if transaction.status == 'confirmed'
|
78
|
+
# next if resource.outcome == 'pending'
|
40
79
|
|
41
|
-
|
42
|
-
resource.
|
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
|
-
|
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
|
77
|
-
|
78
|
-
|
79
|
-
|
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
|
85
|
-
|
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
|
data/lib/istox/helpers/f_math.rb
CHANGED
@@ -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(
|
51
|
-
|
52
|
-
fixed1 = ::BigDecimal.new('1e18')
|
50
|
+
return ::BigDecimal.new("1").to_s if x == y
|
53
51
|
|
54
|
-
|
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 =
|
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(
|
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
|
1
|
+
require "graphlient"
|
2
2
|
|
3
3
|
module Istox
|
4
4
|
class GraphqlClient
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
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
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
2
|
+
class GrpcClient
|
3
|
+
class << self
|
4
|
+
def add_host(host_type, url)
|
5
|
+
unless defined?(@@hosts)
|
6
|
+
@@hosts = {}
|
7
|
+
end
|
6
8
|
|
7
|
-
|
8
|
-
|
9
|
+
@@hosts[host_type] = url
|
10
|
+
end
|
9
11
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
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
|
-
|
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
|
-
|
21
|
-
|
22
|
-
|
32
|
+
def get_host(host_type, service)
|
33
|
+
unless defined?(@@services)
|
34
|
+
@@services = {}
|
35
|
+
end
|
23
36
|
|
24
|
-
|
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
|
-
|
28
|
-
|
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
|
-
|
31
|
-
|
47
|
+
def reinitiate_service(host_type, service)
|
48
|
+
unless defined?(@@services)
|
49
|
+
@@services = {}
|
50
|
+
end
|
32
51
|
|
33
|
-
|
34
|
-
|
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
|
-
|
37
|
-
|
38
|
-
|
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
|
-
|
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
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
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
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
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
|
-
|
44
|
-
|
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
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
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 =
|
17
|
-
|
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,
|
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
|
-
|
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
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
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
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
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
|
-
|
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
|
-
|
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
|
-
#
|
6
|
-
def handle_confirm(
|
4
|
+
|
5
|
+
#overrideable, when blockchain transaction has confirmed
|
6
|
+
def handle_confirm(resource_action)
|
7
7
|
self
|
8
8
|
end
|
9
9
|
|
10
|
-
#
|
11
|
-
def handle_fail(
|
10
|
+
#overrideable, when blockchain transaction has failed
|
11
|
+
def handle_fail(resource_action)
|
12
12
|
self
|
13
13
|
end
|
14
14
|
|
15
|
-
#
|
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
|
-
|
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
|
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
|
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
|
-
|
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
|
data/lib/istox/version.rb
CHANGED
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
|
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-
|
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/
|
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:
|
326
|
+
version: '0'
|
330
327
|
requirements: []
|
331
328
|
rubygems_version: 3.0.6
|
332
329
|
signing_key:
|
data/.rubocop.yml
DELETED
@@ -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
|
data/.solargraph.yml
DELETED
@@ -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
|