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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 7b465403012fd6c2c62f916507601f6a461ec9f6
4
- data.tar.gz: 660aabdd9e68754853025ca889b5a503b01b0a12
2
+ SHA256:
3
+ metadata.gz: 69a13a8a0c2157e87c41dde92831b8ad336aab77a9d58314adfddedf4808509d
4
+ data.tar.gz: 216d48f0578f487fd0420469d7d0a6214b7dc205aae65aab92d21f837fafe723
5
5
  SHA512:
6
- metadata.gz: 4616fb4173f7ffbfd1893cbc6546b5a69bdd1ee823f9af4b3a8497fa9fd4e987d4b350e4fd427a7c236197bd2f6c723058d687f20bf9b770ef44f1703cda420d
7
- data.tar.gz: 1903bffd04558bf5b732547e4be3492c9198b587fe068ba701c5300393b48faa86919238b3973755133dfdca8dfcdd46fe81a04c4f8bf18ffe05b677774744f2
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 coin_payable.rb (see below)
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/coin_payable.rb
68
+ config/initializers/cryptocoin_payable.rb
69
69
 
70
70
  CryptocoinPayable.configure do |config|
71
71
  # config.currency = :usd
@@ -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
- tx_hash: SecureRandom.uuid,
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
- estimated_tx_time: DateTime.iso8601('2017-12-26T21:30:19.858+00:00'),
29
- estimated_tx_value: @coin_amount_due * (percentage.to_f / 100.0),
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
  )
@@ -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
- # tx_hash: string,
19
+ # transaction_hash: string,
20
20
  # block_hash: string,
21
21
  # block_time: nil | string,
22
- # estimated_tx_time: nil | string,
23
- # estimated_tx_value: integer,
22
+ # estimated_time: nil | string,
23
+ # estimated_value: integer,
24
24
  # confirmations: integer,
25
25
  # }
26
- # `block_time` and `estimated_tx_time` are optional strings conforming to
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
- tx_hash: transaction['txid'],
55
+ transaction_hash: transaction['txid'],
56
56
  block_hash: transaction['blockhash'],
57
57
  block_time: parse_timestamp(transaction['blocktime']),
58
- estimated_tx_time: parse_timestamp(transaction['time']),
59
- estimated_tx_value: parse_total_tx_value_block_explorer(transaction['vout'], address),
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
- tx_hash: transaction['hash'],
86
+ transaction_hash: transaction['hash'],
87
87
  block_hash: transaction['block_hash'],
88
88
  block_time: parse_time(transaction['confirmed']),
89
- estimated_tx_time: parse_time(transaction['received']),
90
- estimated_tx_value: parse_total_tx_value_block_cypher(transaction['outputs'], address),
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
- tx_hash: transaction['hash'],
66
+ transaction_hash: transaction['hash'],
67
67
  block_hash: transaction['block_hash'],
68
68
  block_time: nil, # Not supported
69
- estimated_tx_time: parse_timestamp(transaction['timeStamp']),
70
- estimated_tx_value: transaction['value'].to_i, # Units here are 'Wei'
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
- rate = CurrencyConversion.where(coin_type: coin_type).last.price
97
- adapter.convert_main_to_subunit(currency_amount_due / rate.to_f).ceil
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 = CurrencyConversion.where(coin_type: coin_type).last.price
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
- transactions = Adapters.for(payment.coin_type).fetch_transactions(payment.address)
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
- self.class.update_transactions_for(payment)
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
- protected
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.update!(
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
 
@@ -1,3 +1,3 @@
1
1
  module CryptocoinPayable
2
- VERSION = '1.2.0'.freeze
2
+ VERSION = '1.3.0'.freeze
3
3
  end
@@ -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
- tx_hash: '10d9d3927a21d90c573a5fbbb347f409af37219ceb93f7475d6c4cca4231d29f',
11
+ transaction_hash: '10d9d3927a21d90c573a5fbbb347f409af37219ceb93f7475d6c4cca4231d29f',
12
12
  block_hash: '0000000000000000015493ab50fde669130f9b64f0918031a5b6dcc44f14698f',
13
13
  block_time: DateTime.iso8601('2018-10-12T07:28:21.000000000+00:00'),
14
- estimated_tx_time: DateTime.iso8601('2018-10-12T07:28:21.000000000+00:00'),
15
- estimated_tx_value: 4_128_450,
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
- tx_hash: '5bdeaf7829148d7e0e1e7b5233512a2c5ae54ef7ccbc8e68b2f85b7e49c917a0',
9
+ transaction_hash: '5bdeaf7829148d7e0e1e7b5233512a2c5ae54ef7ccbc8e68b2f85b7e49c917a0',
10
10
  block_hash: '0000000000000000048e8ea3fdd2c3a59ddcbcf7575f82cb96ce9fd17da9f2f4',
11
11
  block_time: DateTime.iso8601('2016-09-13T15:41:00.000000000+00:00'),
12
- estimated_tx_time: be_within(1.day).of(DateTime.iso8601('2016-09-13T15:41:00.000000000+00:00')),
13
- estimated_tx_value: 499_000_000,
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
- tx_hash: 'e7bcdb13d9c903973bd8a740054d4c056a559bae67d4e8f6d0a42b4bab552623',
17
+ transaction_hash: 'e7bcdb13d9c903973bd8a740054d4c056a559bae67d4e8f6d0a42b4bab552623',
18
18
  block_hash: '000000000000000001af27feb303ad97af81a5882157f166781784c639f8e896',
19
19
  block_time: DateTime.iso8601('2016-09-13T15:22:42.000000000+00:00'),
20
- estimated_tx_time: be_within(1.day).of(DateTime.iso8601('2016-09-13T15:22:42.000000000+00:00')),
21
- estimated_tx_value: 1_000_000,
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
- tx_hash: '0xa88b799514e9621962e3d0de25e7e0bc7a123e33085f322c7acdb99cc2585c6d',
9
+ transaction_hash: '0xa88b799514e9621962e3d0de25e7e0bc7a123e33085f322c7acdb99cc2585c6d',
10
10
  block_hash: '0x752c50e426f65820f5bf6fd49acbb08d79464f8e7e8ea5b77e2299b69fd6398b',
11
11
  block_time: nil,
12
- estimated_tx_time: be_within(1.day).of(DateTime.iso8601('2018-07-05T12:58:33.000000000+07:00')),
13
- estimated_tx_value: 33_753_640_000_000_000,
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
- tx_hash: '0xb325a8cf241f332bca92c7f715987e4d34be9a6b3bb78d2425c83086b4aced26',
17
+ transaction_hash: '0xb325a8cf241f332bca92c7f715987e4d34be9a6b3bb78d2425c83086b4aced26',
18
18
  block_hash: '0x1c2b73a16fd8c4d25feeccaa2f0bf5c82b8f415f1beaf4d34aaf870daf89689d',
19
19
  block_time: nil,
20
- estimated_tx_time: be_within(1.day).of(DateTime.iso8601('2018-07-05T13:35:07.000000000+07:00')),
21
- estimated_tx_value: 2_190_144_444_444_444,
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
- tx_hash: '0xcd874917be5ad177e7ebd88b5c4a7d4283796e00e43345da5b63fb4f78130b37',
25
+ transaction_hash: '0xcd874917be5ad177e7ebd88b5c4a7d4283796e00e43345da5b63fb4f78130b37',
26
26
  block_hash: '0x4ce71d11146445f123680ea9beba7db968b04dc675caddf60248c9d9d6f5739e',
27
27
  block_time: nil,
28
- estimated_tx_time: be_within(1.day).of(DateTime.iso8601('2018-07-05T13:55:53.000000000+07:00')),
29
- estimated_tx_value: 1_007_518_888_888_888,
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
- tx_hash: '0x799ec2aaafbddbc2e746334f96f59f6127dec62e5693480576db351aaf840bfb',
33
+ transaction_hash: '0x799ec2aaafbddbc2e746334f96f59f6127dec62e5693480576db351aaf840bfb',
34
34
  block_hash: '0xc1361b19b2266e2259ac433b9e18b4fbc81339304988bbc62dd93aa24fac6449',
35
35
  block_time: nil,
36
- estimated_tx_time: be_within(1.day).of(DateTime.iso8601('2018-08-26T16:05:44.000000000+07:00')),
37
- estimated_tx_value: 15_678_420_000_000_000,
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
@@ -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: 20_171_227_225_134) do
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.2.0
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-15 00:00:00.000000000 Z
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.6.12
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