cryptocoin_payable 1.2.0 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +2 -2
- data/cryptocoin_payable.gemspec +3 -0
- data/features/step_definitions/coin_payment_steps.rb +3 -3
- data/features/support/env.rb +2 -0
- data/lib/cryptocoin_payable/adapters/base.rb +4 -4
- data/lib/cryptocoin_payable/adapters/bitcoin.rb +6 -6
- data/lib/cryptocoin_payable/adapters/ethereum.rb +3 -3
- data/lib/cryptocoin_payable/coin_payment.rb +14 -17
- data/lib/cryptocoin_payable/commands/payment_processor.rb +49 -18
- data/lib/cryptocoin_payable/commands/pricing_processor.rb +1 -4
- data/lib/cryptocoin_payable/version.rb +1 -1
- data/lib/generators/cryptocoin_payable/templates/create_coin_payment_transactions.rb +1 -1
- data/spec/acceptance/adapters/bitcoin_cash_spec.rb +3 -3
- data/spec/acceptance/adapters/bitcoin_spec.rb +6 -6
- data/spec/acceptance/adapters/ethereum_spec.rb +12 -12
- data/spec/acceptance/commands/payment_processor_spec.rb +50 -0
- data/spec/dummy/db/development.sqlite3 +0 -0
- data/spec/dummy/db/migrate/{20171227225133_create_coin_payment_transactions.rb → 20181015141952_create_coin_payment_transactions.rb} +1 -1
- data/spec/dummy/db/schema.rb +2 -1
- data/spec/spec_helper.rb +6 -0
- metadata +49 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 69a13a8a0c2157e87c41dde92831b8ad336aab77a9d58314adfddedf4808509d
|
4
|
+
data.tar.gz: 216d48f0578f487fd0420469d7d0a6214b7dc205aae65aab92d21f837fafe723
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f3ceadd2dd62f11a419119583a0fbeeaee72418c9d7c318caba1542809a91dbc06f671f6eed7afc1136cc3556ddc5c535df475b501fa741cd03d2270c493ad81
|
7
|
+
data.tar.gz: 0b340f0086b3411eef2df4f434bc46b12166969ddea73741227382c64d78cc8e88fbaeee9843a26eed3cbf64f07821cd3b658bb4cc628a7262616c7ede99e122
|
data/README.md
CHANGED
@@ -48,7 +48,7 @@ And then execute:
|
|
48
48
|
|
49
49
|
$ bundle exec rake db:migrate
|
50
50
|
|
51
|
-
$ populate
|
51
|
+
$ populate cryptocoin_payable.rb (see below)
|
52
52
|
|
53
53
|
$ bundle exec rake cryptocoin_payable:process_prices (see below)
|
54
54
|
|
@@ -65,7 +65,7 @@ And then execute:
|
|
65
65
|
|
66
66
|
### Configuration
|
67
67
|
|
68
|
-
config/initializers/
|
68
|
+
config/initializers/cryptocoin_payable.rb
|
69
69
|
|
70
70
|
CryptocoinPayable.configure do |config|
|
71
71
|
# config.currency = :usd
|
data/cryptocoin_payable.gemspec
CHANGED
@@ -26,12 +26,15 @@ Gem::Specification.new do |spec|
|
|
26
26
|
spec.add_development_dependency 'database_cleaner', '~> 1.7'
|
27
27
|
spec.add_development_dependency 'rails', '>= 4.0.0'
|
28
28
|
spec.add_development_dependency 'rake', '~> 12.3'
|
29
|
+
spec.add_development_dependency 'rspec-benchmark', '~> 0.4'
|
29
30
|
spec.add_development_dependency 'rspec-rails', '~> 3.7'
|
31
|
+
spec.add_development_dependency 'rspec-retry', '~> 0.6'
|
30
32
|
spec.add_development_dependency 'rubocop', '~> 0.59'
|
31
33
|
spec.add_development_dependency 'sqlite3', '~> 1.3'
|
32
34
|
spec.add_development_dependency 'vcr', '~> 4.0'
|
33
35
|
spec.add_development_dependency 'webmock', '~> 3.4'
|
34
36
|
|
37
|
+
spec.add_dependency 'activerecord-import', '~> 0.27'
|
35
38
|
spec.add_dependency 'cash-addr', '~> 0.2'
|
36
39
|
spec.add_dependency 'eth', '0.4.8'
|
37
40
|
spec.add_dependency 'money-tree', '0.10.0'
|
@@ -22,11 +22,11 @@ end
|
|
22
22
|
Given(/^a payment is made for (\d+) percent$/) do |percentage|
|
23
23
|
CryptocoinPayable::Adapters::Bitcoin.any_instance.stub(:fetch_transactions).and_return(
|
24
24
|
[{
|
25
|
-
|
25
|
+
transaction_hash: SecureRandom.uuid,
|
26
26
|
block_hash: '00000000000000606aa74093ed91d657192a3772732ee4d99a7b7be8075eafa2',
|
27
27
|
block_time: DateTime.iso8601('2017-12-26T21:38:44.000+00:00'),
|
28
|
-
|
29
|
-
|
28
|
+
estimated_time: DateTime.iso8601('2017-12-26T21:30:19.858+00:00'),
|
29
|
+
estimated_value: @coin_amount_due * (percentage.to_f / 100.0),
|
30
30
|
confirmations: 1
|
31
31
|
}]
|
32
32
|
)
|
data/features/support/env.rb
CHANGED
@@ -4,6 +4,8 @@ ENV['RAILS_ROOT'] ||= File.dirname(__FILE__) + '../../../spec/dummy'
|
|
4
4
|
require 'cucumber/rails'
|
5
5
|
require 'cucumber/rspec/doubles'
|
6
6
|
|
7
|
+
# ActiveRecord::Base.logger = Logger.new(STDOUT) if defined?(ActiveRecord::Base)
|
8
|
+
|
7
9
|
# Remove/comment out the lines below if your app doesn't have a database.
|
8
10
|
# For some databases (like MongoDB and CouchDB) you may need to use :truncation instead.
|
9
11
|
begin
|
@@ -16,14 +16,14 @@ module CryptocoinPayable
|
|
16
16
|
# Queries an API like etherscan.io and returns a list of transactions
|
17
17
|
# which conform to the following shape:
|
18
18
|
# {
|
19
|
-
#
|
19
|
+
# transaction_hash: string,
|
20
20
|
# block_hash: string,
|
21
21
|
# block_time: nil | string,
|
22
|
-
#
|
23
|
-
#
|
22
|
+
# estimated_time: nil | string,
|
23
|
+
# estimated_value: integer,
|
24
24
|
# confirmations: integer,
|
25
25
|
# }
|
26
|
-
# `block_time` and `
|
26
|
+
# `block_time` and `estimated_time` are optional strings conforming to
|
27
27
|
# date format ISO 8601.
|
28
28
|
#
|
29
29
|
# Can optionally raise ApiLimitedReached if needed.
|
@@ -52,11 +52,11 @@ module CryptocoinPayable
|
|
52
52
|
|
53
53
|
def convert_block_explorer_transactions(transaction, address)
|
54
54
|
{
|
55
|
-
|
55
|
+
transaction_hash: transaction['txid'],
|
56
56
|
block_hash: transaction['blockhash'],
|
57
57
|
block_time: parse_timestamp(transaction['blocktime']),
|
58
|
-
|
59
|
-
|
58
|
+
estimated_time: parse_timestamp(transaction['time']),
|
59
|
+
estimated_value: parse_total_tx_value_block_explorer(transaction['vout'], address),
|
60
60
|
confirmations: transaction['confirmations']
|
61
61
|
}
|
62
62
|
end
|
@@ -83,11 +83,11 @@ module CryptocoinPayable
|
|
83
83
|
|
84
84
|
def convert_block_cypher_transactions(transaction, address)
|
85
85
|
{
|
86
|
-
|
86
|
+
transaction_hash: transaction['hash'],
|
87
87
|
block_hash: transaction['block_hash'],
|
88
88
|
block_time: parse_time(transaction['confirmed']),
|
89
|
-
|
90
|
-
|
89
|
+
estimated_time: parse_time(transaction['received']),
|
90
|
+
estimated_value: parse_total_tx_value_block_cypher(transaction['outputs'], address),
|
91
91
|
confirmations: transaction['confirmations'].to_i
|
92
92
|
}
|
93
93
|
end
|
@@ -63,11 +63,11 @@ module CryptocoinPayable
|
|
63
63
|
# }
|
64
64
|
def convert_transactions(transaction, _address)
|
65
65
|
{
|
66
|
-
|
66
|
+
transaction_hash: transaction['hash'],
|
67
67
|
block_hash: transaction['block_hash'],
|
68
68
|
block_time: nil, # Not supported
|
69
|
-
|
70
|
-
|
69
|
+
estimated_time: parse_timestamp(transaction['timeStamp']),
|
70
|
+
estimated_value: transaction['value'].to_i, # Units here are 'Wei'
|
71
71
|
confirmations: transaction['confirmations'].to_i
|
72
72
|
}
|
73
73
|
end
|
@@ -4,20 +4,7 @@ require 'state_machine'
|
|
4
4
|
module CryptocoinPayable
|
5
5
|
class CoinPayment < ActiveRecord::Base
|
6
6
|
belongs_to :payable, polymorphic: true
|
7
|
-
|
8
|
-
has_many :transactions, class_name: 'CryptocoinPayable::CoinPaymentTransaction' do
|
9
|
-
def create_from_tx_data!(tx_data, coin_conversion)
|
10
|
-
create!(
|
11
|
-
estimated_value: tx_data[:estimated_tx_value],
|
12
|
-
transaction_hash: tx_data[:tx_hash],
|
13
|
-
block_hash: tx_data[:block_hash],
|
14
|
-
block_time: tx_data[:block_time],
|
15
|
-
estimated_time: tx_data[:estimated_tx_time],
|
16
|
-
coin_conversion: coin_conversion,
|
17
|
-
confirmations: tx_data[:confirmations]
|
18
|
-
)
|
19
|
-
end
|
20
|
-
end
|
7
|
+
has_many :transactions, class_name: 'CryptocoinPayable::CoinPaymentTransaction'
|
21
8
|
|
22
9
|
validates :reason, presence: true
|
23
10
|
validates :price, presence: true
|
@@ -93,8 +80,18 @@ module CryptocoinPayable
|
|
93
80
|
end
|
94
81
|
|
95
82
|
def calculate_coin_amount_due
|
96
|
-
|
97
|
-
|
83
|
+
adapter.convert_main_to_subunit(currency_amount_due / coin_conversion.to_f).ceil
|
84
|
+
end
|
85
|
+
|
86
|
+
def coin_conversion
|
87
|
+
@coin_conversion ||= CurrencyConversion.where(coin_type: coin_type).last.price
|
88
|
+
end
|
89
|
+
|
90
|
+
def update_coin_amount_due(rate: coin_conversion)
|
91
|
+
update!(
|
92
|
+
coin_amount_due: calculate_coin_amount_due,
|
93
|
+
coin_conversion: rate
|
94
|
+
)
|
98
95
|
end
|
99
96
|
|
100
97
|
def transactions_confirmed?
|
@@ -112,7 +109,7 @@ module CryptocoinPayable
|
|
112
109
|
def populate_currency_and_amount_due
|
113
110
|
self.currency ||= CryptocoinPayable.configuration.currency
|
114
111
|
self.coin_amount_due = calculate_coin_amount_due
|
115
|
-
self.coin_conversion =
|
112
|
+
self.coin_conversion = coin_conversion
|
116
113
|
end
|
117
114
|
|
118
115
|
def populate_address
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'activerecord-import'
|
2
|
+
|
1
3
|
module CryptocoinPayable
|
2
4
|
class PaymentProcessor
|
3
5
|
def self.perform
|
@@ -5,22 +7,7 @@ module CryptocoinPayable
|
|
5
7
|
end
|
6
8
|
|
7
9
|
def self.update_transactions_for(payment)
|
8
|
-
|
9
|
-
|
10
|
-
transactions.each do |tx|
|
11
|
-
tx.symbolize_keys!
|
12
|
-
|
13
|
-
transaction = payment.transactions.find_by_transaction_hash(tx[:tx_hash])
|
14
|
-
if transaction
|
15
|
-
transaction.update(confirmations: tx[:confirmations])
|
16
|
-
else
|
17
|
-
payment.transactions.create_from_tx_data!(tx, payment.coin_conversion)
|
18
|
-
payment.update(
|
19
|
-
coin_amount_due: payment.calculate_coin_amount_due,
|
20
|
-
coin_conversion: CurrencyConversion.where(coin_type: payment.coin_type).last.price
|
21
|
-
)
|
22
|
-
end
|
23
|
-
end
|
10
|
+
new.update_transactions_for(payment)
|
24
11
|
end
|
25
12
|
|
26
13
|
def perform
|
@@ -32,7 +19,7 @@ module CryptocoinPayable
|
|
32
19
|
next if payment.confirmed?
|
33
20
|
|
34
21
|
begin
|
35
|
-
|
22
|
+
update_transactions_for(payment)
|
36
23
|
rescue StandardError => error
|
37
24
|
STDERR.puts 'PaymentProcessor: Unknown error encountered, skipping transaction'
|
38
25
|
STDERR.puts error
|
@@ -48,7 +35,51 @@ module CryptocoinPayable
|
|
48
35
|
end
|
49
36
|
end
|
50
37
|
|
51
|
-
|
38
|
+
def update_transactions_for(payment)
|
39
|
+
transactions = Adapters.for(payment.coin_type).fetch_transactions(payment.address)
|
40
|
+
|
41
|
+
payment.transaction do
|
42
|
+
if ActiveRecord::Base.connection.supports_on_duplicate_key_update?
|
43
|
+
update_via_bulk_insert(payment, transactions)
|
44
|
+
else
|
45
|
+
update_via_many_insert(payment, transactions)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
transactions
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def update_via_bulk_insert(payment, transactions)
|
55
|
+
transactions.each do |t|
|
56
|
+
t[:coin_conversion] = payment.coin_conversion
|
57
|
+
t[:coin_payment_id] = payment.id
|
58
|
+
end
|
59
|
+
|
60
|
+
CoinPaymentTransaction.import(
|
61
|
+
transactions,
|
62
|
+
on_duplicate_key_update: {
|
63
|
+
conflict_target: [:transaction_hash],
|
64
|
+
columns: [:coin_conversion]
|
65
|
+
}
|
66
|
+
)
|
67
|
+
payment.reload
|
68
|
+
payment.update_coin_amount_due
|
69
|
+
end
|
70
|
+
|
71
|
+
def update_via_many_insert(payment, transactions)
|
72
|
+
transactions.each do |tx|
|
73
|
+
transaction = payment.transactions.find_by_transaction_hash(tx[:transaction_hash])
|
74
|
+
if transaction
|
75
|
+
transaction.update(confirmations: tx[:confirmations])
|
76
|
+
else
|
77
|
+
tx[:coin_conversion] = payment.coin_conversion
|
78
|
+
payment.transactions.create!(tx)
|
79
|
+
payment.update_coin_amount_due
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
52
83
|
|
53
84
|
def update_payment_state(payment)
|
54
85
|
if payment.currency_amount_paid >= payment.price
|
@@ -25,10 +25,7 @@ module CryptocoinPayable
|
|
25
25
|
# Loop through all unpaid payments and update them with the new price if
|
26
26
|
# it has been 30 mins since they have been updated.
|
27
27
|
CoinPayment.unpaid.stale.find_each do |payment|
|
28
|
-
payment.
|
29
|
-
coin_amount_due: payment.calculate_coin_amount_due,
|
30
|
-
coin_conversion: rates[payment.coin_type.to_sym].price
|
31
|
-
)
|
28
|
+
payment.update_coin_amount_due(coin_conversion: rates[payment.coin_type.to_sym].price)
|
32
29
|
end
|
33
30
|
end
|
34
31
|
|
@@ -2,7 +2,7 @@ class CreateCoinPaymentTransactions < ActiveRecord::Migration[5.1]
|
|
2
2
|
def change
|
3
3
|
create_table :coin_payment_transactions do |t|
|
4
4
|
t.decimal :estimated_value, precision: 24, scale: 0
|
5
|
-
t.string :transaction_hash
|
5
|
+
t.string :transaction_hash, index: { unique: true }
|
6
6
|
t.string :block_hash
|
7
7
|
t.datetime :block_time
|
8
8
|
t.datetime :estimated_time
|
@@ -8,11 +8,11 @@ describe CryptocoinPayable::Adapters::BitcoinCash, :vcr do
|
|
8
8
|
expect(response).to eq(
|
9
9
|
[
|
10
10
|
{
|
11
|
-
|
11
|
+
transaction_hash: '10d9d3927a21d90c573a5fbbb347f409af37219ceb93f7475d6c4cca4231d29f',
|
12
12
|
block_hash: '0000000000000000015493ab50fde669130f9b64f0918031a5b6dcc44f14698f',
|
13
13
|
block_time: DateTime.iso8601('2018-10-12T07:28:21.000000000+00:00'),
|
14
|
-
|
15
|
-
|
14
|
+
estimated_time: DateTime.iso8601('2018-10-12T07:28:21.000000000+00:00'),
|
15
|
+
estimated_value: 4_128_450,
|
16
16
|
confirmations: 2
|
17
17
|
}
|
18
18
|
]
|
@@ -6,19 +6,19 @@ describe CryptocoinPayable::Adapters::Bitcoin, :vcr do
|
|
6
6
|
expect(response).to match_array(
|
7
7
|
[
|
8
8
|
{
|
9
|
-
|
9
|
+
transaction_hash: '5bdeaf7829148d7e0e1e7b5233512a2c5ae54ef7ccbc8e68b2f85b7e49c917a0',
|
10
10
|
block_hash: '0000000000000000048e8ea3fdd2c3a59ddcbcf7575f82cb96ce9fd17da9f2f4',
|
11
11
|
block_time: DateTime.iso8601('2016-09-13T15:41:00.000000000+00:00'),
|
12
|
-
|
13
|
-
|
12
|
+
estimated_time: be_within(1.day).of(DateTime.iso8601('2016-09-13T15:41:00.000000000+00:00')),
|
13
|
+
estimated_value: 499_000_000,
|
14
14
|
confirmations: 116_077
|
15
15
|
},
|
16
16
|
{
|
17
|
-
|
17
|
+
transaction_hash: 'e7bcdb13d9c903973bd8a740054d4c056a559bae67d4e8f6d0a42b4bab552623',
|
18
18
|
block_hash: '000000000000000001af27feb303ad97af81a5882157f166781784c639f8e896',
|
19
19
|
block_time: DateTime.iso8601('2016-09-13T15:22:42.000000000+00:00'),
|
20
|
-
|
21
|
-
|
20
|
+
estimated_time: be_within(1.day).of(DateTime.iso8601('2016-09-13T15:22:42.000000000+00:00')),
|
21
|
+
estimated_value: 1_000_000,
|
22
22
|
confirmations: 116_080
|
23
23
|
}
|
24
24
|
]
|
@@ -6,35 +6,35 @@ describe CryptocoinPayable::Adapters::Ethereum, :vcr do
|
|
6
6
|
expect(response).to match_array(
|
7
7
|
[
|
8
8
|
{
|
9
|
-
|
9
|
+
transaction_hash: '0xa88b799514e9621962e3d0de25e7e0bc7a123e33085f322c7acdb99cc2585c6d',
|
10
10
|
block_hash: '0x752c50e426f65820f5bf6fd49acbb08d79464f8e7e8ea5b77e2299b69fd6398b',
|
11
11
|
block_time: nil,
|
12
|
-
|
13
|
-
|
12
|
+
estimated_time: be_within(1.day).of(DateTime.iso8601('2018-07-05T12:58:33.000000000+07:00')),
|
13
|
+
estimated_value: 33_753_640_000_000_000,
|
14
14
|
confirmations: 569_771
|
15
15
|
},
|
16
16
|
{
|
17
|
-
|
17
|
+
transaction_hash: '0xb325a8cf241f332bca92c7f715987e4d34be9a6b3bb78d2425c83086b4aced26',
|
18
18
|
block_hash: '0x1c2b73a16fd8c4d25feeccaa2f0bf5c82b8f415f1beaf4d34aaf870daf89689d',
|
19
19
|
block_time: nil,
|
20
|
-
|
21
|
-
|
20
|
+
estimated_time: be_within(1.day).of(DateTime.iso8601('2018-07-05T13:35:07.000000000+07:00')),
|
21
|
+
estimated_value: 2_190_144_444_444_444,
|
22
22
|
confirmations: 569_629
|
23
23
|
},
|
24
24
|
{
|
25
|
-
|
25
|
+
transaction_hash: '0xcd874917be5ad177e7ebd88b5c4a7d4283796e00e43345da5b63fb4f78130b37',
|
26
26
|
block_hash: '0x4ce71d11146445f123680ea9beba7db968b04dc675caddf60248c9d9d6f5739e',
|
27
27
|
block_time: nil,
|
28
|
-
|
29
|
-
|
28
|
+
estimated_time: be_within(1.day).of(DateTime.iso8601('2018-07-05T13:55:53.000000000+07:00')),
|
29
|
+
estimated_value: 1_007_518_888_888_888,
|
30
30
|
confirmations: 569_549
|
31
31
|
},
|
32
32
|
{
|
33
|
-
|
33
|
+
transaction_hash: '0x799ec2aaafbddbc2e746334f96f59f6127dec62e5693480576db351aaf840bfb',
|
34
34
|
block_hash: '0xc1361b19b2266e2259ac433b9e18b4fbc81339304988bbc62dd93aa24fac6449',
|
35
35
|
block_time: nil,
|
36
|
-
|
37
|
-
|
36
|
+
estimated_time: be_within(1.day).of(DateTime.iso8601('2018-08-26T16:05:44.000000000+07:00')),
|
37
|
+
estimated_value: 15_678_420_000_000_000,
|
38
38
|
confirmations: 261_969
|
39
39
|
}
|
40
40
|
]
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
require 'database_cleaner'
|
3
|
+
require 'cryptocoin_payable/orm/activerecord'
|
4
|
+
|
5
|
+
describe CryptocoinPayable::PaymentProcessor do
|
6
|
+
def build_fake_transactions_data
|
7
|
+
transactions = []
|
8
|
+
300.times do
|
9
|
+
transactions << {
|
10
|
+
transaction_hash: '5bdeaf7829148d7e0e1e7b5233512a2c5ae54ef7ccbc8e68b2f85b7e49c917a0',
|
11
|
+
block_hash: '0000000000000000048e8ea3fdd2c3a59ddcbcf7575f82cb96ce9fd17da9f2f4',
|
12
|
+
block_time: DateTime.iso8601('2016-09-13T15:41:00.000000000+00:00'),
|
13
|
+
estimated_time: DateTime.iso8601('2016-09-13T15:41:00.000000000+00:00'),
|
14
|
+
estimated_value: 499_000_000,
|
15
|
+
confirmations: 116_077
|
16
|
+
}
|
17
|
+
end
|
18
|
+
transactions
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'when testing performance of database interaction' do
|
22
|
+
before(:all) do
|
23
|
+
ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: 'spec/dummy/db/test.sqlite3')
|
24
|
+
DatabaseCleaner.strategy = :truncation
|
25
|
+
GC.disable
|
26
|
+
end
|
27
|
+
|
28
|
+
after(:all) do
|
29
|
+
GC.enable
|
30
|
+
end
|
31
|
+
|
32
|
+
before do
|
33
|
+
DatabaseCleaner.clean
|
34
|
+
CryptocoinPayable::CurrencyConversion.create!(coin_type: :btc, currency: 1, price: 1)
|
35
|
+
adapter = CryptocoinPayable::Adapters.bitcoin_adapter
|
36
|
+
allow(adapter).to receive(:fetch_transactions) { build_fake_transactions_data }
|
37
|
+
end
|
38
|
+
|
39
|
+
after do
|
40
|
+
DatabaseCleaner.clean
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should insert 300 transactions in under 300ms', retry: 3 do
|
44
|
+
payment = CryptocoinPayable::CoinPayment.create!(reason: 'test', price: 1, coin_type: :btc)
|
45
|
+
payment.update(address: '3HR9xYD7MybbE7JLVTjwijYse48BtfEKni')
|
46
|
+
|
47
|
+
expect { subject.update_transactions_for(payment) }.to perform_under(300).ms
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
Binary file
|
@@ -2,7 +2,7 @@ class CreateCoinPaymentTransactions < ActiveRecord::Migration[5.1]
|
|
2
2
|
def change
|
3
3
|
create_table :coin_payment_transactions do |t|
|
4
4
|
t.decimal :estimated_value, precision: 24, scale: 0
|
5
|
-
t.string :transaction_hash
|
5
|
+
t.string :transaction_hash, index: { unique: true }
|
6
6
|
t.string :block_hash
|
7
7
|
t.datetime :block_time
|
8
8
|
t.datetime :estimated_time
|
data/spec/dummy/db/schema.rb
CHANGED
@@ -10,7 +10,7 @@
|
|
10
10
|
#
|
11
11
|
# It's strongly recommended that you check this file into your version control system.
|
12
12
|
|
13
|
-
ActiveRecord::Schema.define(version:
|
13
|
+
ActiveRecord::Schema.define(version: 20_181_015_141_952) do
|
14
14
|
create_table 'coin_payment_transactions', force: :cascade do |t|
|
15
15
|
t.decimal 'estimated_value', precision: 24
|
16
16
|
t.string 'transaction_hash'
|
@@ -21,6 +21,7 @@ ActiveRecord::Schema.define(version: 20_171_227_225_134) do
|
|
21
21
|
t.decimal 'coin_conversion', precision: 24
|
22
22
|
t.integer 'confirmations', default: 0
|
23
23
|
t.index ['coin_payment_id'], name: 'index_coin_payment_transactions_on_coin_payment_id'
|
24
|
+
t.index ['transaction_hash'], name: 'index_coin_payment_transactions_on_transaction_hash', unique: true
|
24
25
|
end
|
25
26
|
|
26
27
|
create_table 'coin_payments', force: :cascade do |t|
|
data/spec/spec_helper.rb
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
require 'vcr'
|
2
2
|
require 'webmock/rspec'
|
3
3
|
require 'active_support/time'
|
4
|
+
require 'rspec-benchmark'
|
5
|
+
require 'rspec/retry'
|
6
|
+
|
7
|
+
# ActiveRecord::Base.logger = Logger.new(STDOUT) if defined?(ActiveRecord::Base)
|
4
8
|
|
5
9
|
VCR.configure do |config|
|
6
10
|
config.cassette_library_dir = 'spec/fixtures/vcr_cassettes'
|
@@ -59,6 +63,8 @@ RSpec.configure do |config|
|
|
59
63
|
end
|
60
64
|
end
|
61
65
|
|
66
|
+
config.include RSpec::Benchmark::Matchers
|
67
|
+
|
62
68
|
# The settings below are suggested to provide a good initial experience
|
63
69
|
# with RSpec, but feel free to customize to your heart's content.
|
64
70
|
# # This allows you to limit a spec run to individual examples or groups
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cryptocoin_payable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jonathan Salis
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2018-10-
|
12
|
+
date: 2018-10-16 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activerecord
|
@@ -95,6 +95,20 @@ dependencies:
|
|
95
95
|
- - "~>"
|
96
96
|
- !ruby/object:Gem::Version
|
97
97
|
version: '12.3'
|
98
|
+
- !ruby/object:Gem::Dependency
|
99
|
+
name: rspec-benchmark
|
100
|
+
requirement: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - "~>"
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '0.4'
|
105
|
+
type: :development
|
106
|
+
prerelease: false
|
107
|
+
version_requirements: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - "~>"
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '0.4'
|
98
112
|
- !ruby/object:Gem::Dependency
|
99
113
|
name: rspec-rails
|
100
114
|
requirement: !ruby/object:Gem::Requirement
|
@@ -109,6 +123,20 @@ dependencies:
|
|
109
123
|
- - "~>"
|
110
124
|
- !ruby/object:Gem::Version
|
111
125
|
version: '3.7'
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: rspec-retry
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
requirements:
|
130
|
+
- - "~>"
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: '0.6'
|
133
|
+
type: :development
|
134
|
+
prerelease: false
|
135
|
+
version_requirements: !ruby/object:Gem::Requirement
|
136
|
+
requirements:
|
137
|
+
- - "~>"
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: '0.6'
|
112
140
|
- !ruby/object:Gem::Dependency
|
113
141
|
name: rubocop
|
114
142
|
requirement: !ruby/object:Gem::Requirement
|
@@ -165,6 +193,20 @@ dependencies:
|
|
165
193
|
- - "~>"
|
166
194
|
- !ruby/object:Gem::Version
|
167
195
|
version: '3.4'
|
196
|
+
- !ruby/object:Gem::Dependency
|
197
|
+
name: activerecord-import
|
198
|
+
requirement: !ruby/object:Gem::Requirement
|
199
|
+
requirements:
|
200
|
+
- - "~>"
|
201
|
+
- !ruby/object:Gem::Version
|
202
|
+
version: '0.27'
|
203
|
+
type: :runtime
|
204
|
+
prerelease: false
|
205
|
+
version_requirements: !ruby/object:Gem::Requirement
|
206
|
+
requirements:
|
207
|
+
- - "~>"
|
208
|
+
- !ruby/object:Gem::Version
|
209
|
+
version: '0.27'
|
168
210
|
- !ruby/object:Gem::Dependency
|
169
211
|
name: cash-addr
|
170
212
|
requirement: !ruby/object:Gem::Requirement
|
@@ -276,6 +318,7 @@ files:
|
|
276
318
|
- spec/acceptance/adapters/bitcoin_cash_spec.rb
|
277
319
|
- spec/acceptance/adapters/bitcoin_spec.rb
|
278
320
|
- spec/acceptance/adapters/ethereum_spec.rb
|
321
|
+
- spec/acceptance/commands/payment_processor_spec.rb
|
279
322
|
- spec/dummy/README.rdoc
|
280
323
|
- spec/dummy/Rakefile
|
281
324
|
- spec/dummy/app/assets/images/.keep
|
@@ -314,8 +357,8 @@ files:
|
|
314
357
|
- spec/dummy/db/development.sqlite3
|
315
358
|
- spec/dummy/db/migrate/20140510023211_create_widgets.rb
|
316
359
|
- spec/dummy/db/migrate/20171227225132_create_coin_payments.rb
|
317
|
-
- spec/dummy/db/migrate/20171227225133_create_coin_payment_transactions.rb
|
318
360
|
- spec/dummy/db/migrate/20171227225134_create_currency_conversions.rb
|
361
|
+
- spec/dummy/db/migrate/20181015141952_create_coin_payment_transactions.rb
|
319
362
|
- spec/dummy/db/schema.rb
|
320
363
|
- spec/dummy/lib/assets/.keep
|
321
364
|
- spec/dummy/log/.keep
|
@@ -355,7 +398,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
355
398
|
version: 1.3.6
|
356
399
|
requirements: []
|
357
400
|
rubyforge_project:
|
358
|
-
rubygems_version: 2.
|
401
|
+
rubygems_version: 2.7.7
|
359
402
|
signing_key:
|
360
403
|
specification_version: 4
|
361
404
|
summary: Cryptocurrency payment processor
|
@@ -372,6 +415,7 @@ test_files:
|
|
372
415
|
- spec/acceptance/adapters/bitcoin_cash_spec.rb
|
373
416
|
- spec/acceptance/adapters/bitcoin_spec.rb
|
374
417
|
- spec/acceptance/adapters/ethereum_spec.rb
|
418
|
+
- spec/acceptance/commands/payment_processor_spec.rb
|
375
419
|
- spec/dummy/README.rdoc
|
376
420
|
- spec/dummy/Rakefile
|
377
421
|
- spec/dummy/app/assets/images/.keep
|
@@ -410,8 +454,8 @@ test_files:
|
|
410
454
|
- spec/dummy/db/development.sqlite3
|
411
455
|
- spec/dummy/db/migrate/20140510023211_create_widgets.rb
|
412
456
|
- spec/dummy/db/migrate/20171227225132_create_coin_payments.rb
|
413
|
-
- spec/dummy/db/migrate/20171227225133_create_coin_payment_transactions.rb
|
414
457
|
- spec/dummy/db/migrate/20171227225134_create_currency_conversions.rb
|
458
|
+
- spec/dummy/db/migrate/20181015141952_create_coin_payment_transactions.rb
|
415
459
|
- spec/dummy/db/schema.rb
|
416
460
|
- spec/dummy/lib/assets/.keep
|
417
461
|
- spec/dummy/log/.keep
|