coins_paid_rails 1.0.0

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 76dfc07ca328248272a643ae517e9f4e3adfc8d4199df23c4e18aea9f90ee484
4
+ data.tar.gz: 522e768d858bc97704304a6021b42e06c5905cbebd151556de6d326a6fc5f62b
5
+ SHA512:
6
+ metadata.gz: 25c3a98da0c552ac54e791d4df5cf939ffdb47be6a6bf17dc1de240e03769c69dc2b1edfaaf492e52c53eec3b2ee20a105bb17bc04a6e2af410adb09dbbdbd42
7
+ data.tar.gz: e06207597934bcb1279527225c76ac08ffb0273cba8ad36d2db96a9a90e3fa3ac4e899b5c1a01f220ff3799ee43ee28ba00f6887a38634b33bd8905d434b01bb
@@ -0,0 +1,108 @@
1
+ version: 2.0
2
+ defaults: &defaults
3
+ docker:
4
+ - image: circleci/ruby:2.5-stretch-node
5
+ working_directory: ~/coins_paid
6
+
7
+ jobs:
8
+ checkout_code:
9
+ <<: *defaults
10
+ steps:
11
+ - checkout
12
+ - run: mkdir log
13
+ - save_cache:
14
+ key: v1-repo-{{ .Environment.CIRCLE_SHA1 }}
15
+ paths:
16
+ - ~/coins_paid
17
+
18
+ download_cc_reporter:
19
+ <<: *defaults
20
+ steps:
21
+ - run:
22
+ name: Download cc-test-reporter
23
+ command: |
24
+ mkdir -p cc/
25
+ curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc/cc-test-reporter
26
+ chmod +x ./cc/cc-test-reporter
27
+ - persist_to_workspace:
28
+ root: ~/coins_paid
29
+ paths:
30
+ - cc/cc-test-reporter
31
+
32
+ run_bundler:
33
+ <<: *defaults
34
+ steps:
35
+ - restore_cache:
36
+ key: v1-repo-{{ .Environment.CIRCLE_SHA1 }}
37
+ - restore_cache:
38
+ key: v1-bundle-{{ checksum "Gemfile" }}
39
+ - run: echo "export rvm_ignore_gemsets_flag=1" >> ~/.rvmrc
40
+ - run: sudo apt-get update && sudo apt-get install -y libsodium-dev
41
+ - run: bundle check --path=vendor/bundle || bundle install --path=vendor/bundle --jobs=4 --retry=3
42
+ - save_cache:
43
+ key: v1-bundle-{{ checksum "Gemfile" }}
44
+ paths:
45
+ - ~/coins_paid/vendor/bundle
46
+
47
+ run_rspec_tests:
48
+ <<: *defaults
49
+ docker:
50
+ - image: circleci/ruby:2.5-stretch-node
51
+ environment:
52
+ RACK_ENV: "test"
53
+ CIRCLE_ARTIFACTS: "./tmp"
54
+ steps:
55
+ - restore_cache:
56
+ key: v1-repo-{{ .Environment.CIRCLE_SHA1 }}
57
+ - restore_cache:
58
+ key: v1-bundle-{{ checksum "Gemfile" }}
59
+ - attach_workspace:
60
+ at: ~/coins_paid
61
+ - run: sudo apt-get update && sudo apt-get install -y libsodium-dev
62
+ - run: bundle check --path vendor/bundle
63
+ - run: bundle exec rspec spec
64
+ - run: ./cc/cc-test-reporter format-coverage -t simplecov -o cc/codeclimate.rspec.json tmp/coverage/.resultset.json
65
+ - persist_to_workspace:
66
+ root: ~/coins_paid
67
+ paths:
68
+ - cc/codeclimate.rspec.json
69
+
70
+ upload_cc_coverage:
71
+ <<: *defaults
72
+ steps:
73
+ - attach_workspace:
74
+ at: ~/coins_paid
75
+ - run:
76
+ name: Upload coverage results to Code Climate
77
+ command: |
78
+ ./cc/cc-test-reporter upload-coverage -i cc/codeclimate.rspec.json
79
+
80
+ deploy:
81
+ <<: *defaults
82
+ steps:
83
+ - restore_cache:
84
+ key: v1-repo-{{ .Environment.CIRCLE_SHA1 }}
85
+ - restore_cache:
86
+ key: v1-bundle-{{ checksum "Gemfile" }}
87
+ - run: mkdir -p ~/.ssh && ssh-keyscan -H github.com >> ~/.ssh/known_hosts
88
+ - run: sudo apt-get update && sudo apt-get install -y libsodium-dev
89
+ - run: bundle check --path vendor/bundle
90
+ - run: bundle exec rake deploy:branch_or_label
91
+
92
+ workflows:
93
+ version: 2
94
+ build_test_deploy:
95
+ jobs:
96
+ - checkout_code
97
+ - download_cc_reporter:
98
+ requires:
99
+ - checkout_code
100
+ - run_bundler:
101
+ requires:
102
+ - download_cc_reporter
103
+ - run_rspec_tests:
104
+ requires:
105
+ - run_bundler
106
+ - upload_cc_coverage:
107
+ requires:
108
+ - run_rspec_tests
@@ -0,0 +1,3 @@
1
+ /*.gem
2
+ /Gemfile.lock
3
+ **/test.db
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --colour
2
+ --require spec_helper
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source "http://www.rubygems.org"
2
+
3
+ gemspec
4
+
5
+ group :test do
6
+ gem 'simplecov', require: false
7
+ gem 'sqlite3'
8
+ gem 'rspec-its'
9
+ end
@@ -0,0 +1,15 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'coins_paid_rails'
3
+ s.authors = ['Artem Biserov(artembiserov)', 'Oleg Ivanov(morhekil)']
4
+ s.version = '1.0.0'
5
+ s.files = `git ls-files`.split("\n")
6
+ s.summary = 'CoinsPaid Rails Integration'
7
+ s.license = 'MIT'
8
+
9
+ s.add_runtime_dependency 'coins_paid_api', '~> 1.0'
10
+ s.add_runtime_dependency 'activerecord', '>= 4.2.0'
11
+ s.add_runtime_dependency 'dry-initializer', '~> 3.0'
12
+ s.add_runtime_dependency 'dry-struct', '~> 1.0'
13
+ s.add_development_dependency 'rspec-rails', '~> 3.0'
14
+ end
15
+
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+ require 'dry-struct'
3
+ require 'dry-initializer'
4
+ require_relative 'coins_paid/address'
5
+ require_relative 'coins_paid/coins_paid_address'
6
+ require_relative 'coins_paid/qr_code'
7
+
8
+ module CoinsPaid
9
+ module_function
10
+
11
+ UnknownCurrency = Class.new RuntimeError
12
+
13
+ DEFAULT_CONVERT_TO = ENV['COINS_PAID_CURRENCY']
14
+
15
+ CRYPTO_CURRENCIES = {
16
+ 'BTC' => 'bitcoin',
17
+ 'ETH' => 'ethereum',
18
+ 'LTC' => 'litecoin'
19
+ }.freeze
20
+
21
+ def address(foreign_id, currency:)
22
+ Address.new(foreign_id: foreign_id, currency: currency, convert_to: DEFAULT_CONVERT_TO).call
23
+ end
24
+
25
+ def qr_code(player_id, currency:, label:, message:)
26
+ QrCode.new(player_id, currency: currency, label: label, message: message)
27
+ end
28
+
29
+ def currency(name)
30
+ CoinsPaid::API.currencies_list.find { |item| item.currency == name } || raise(UnknownCurrency, name)
31
+ end
32
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CoinsPaid
4
+ class Address
5
+ module Types
6
+ include Dry.Types()
7
+ end
8
+
9
+ class Data < Dry::Struct
10
+ attribute :foreign_id, Types::Coercible::String
11
+ attribute :currency, Types::String
12
+ attribute :convert_to, Types::String
13
+ end
14
+
15
+ include Dry::Initializer.define -> do
16
+ param :request_data, Data
17
+ end
18
+
19
+ def call
20
+ CoinsPaidAddress.find_or_create_by!(request_data.attributes.slice(:foreign_id, :currency)) do |address|
21
+ response = CoinsPaid::API.take_address(request_data.attributes)
22
+ address.assign_attributes(response.attributes)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CoinsPaid
4
+ class CoinsPaidAddress < ActiveRecord::Base
5
+ end
6
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CoinsPaid
4
+ class QrCode
5
+ include Dry::Initializer.define -> do
6
+ param :player_id
7
+ option :currency
8
+ option :label
9
+ option :message
10
+ end
11
+
12
+ def url
13
+ "#{token_type}:#{address}?label=#{encode(label)}&message=#{encode(message)}"
14
+ end
15
+
16
+ def address
17
+ @address ||= CoinsPaid.address(player_id, currency: currency).address
18
+ end
19
+
20
+ def svg
21
+ RQRCode::QRCode.new(url).as_svg(
22
+ offset: 0,
23
+ color: '000',
24
+ shape_rendering: 'crispEdges',
25
+ module_size: 3,
26
+ standalone: true
27
+ )
28
+ end
29
+
30
+ private
31
+
32
+ def token_type
33
+ CRYPTO_CURRENCIES.fetch(currency)
34
+ end
35
+
36
+ def encode(string)
37
+ URI.encode_www_form_component(string)
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,2 @@
1
+ # frozen_string_literal: true
2
+ require_relative 'coins_paid'
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CoinsPaid
4
+ module MigrationData
5
+ module_function
6
+
7
+ def get
8
+ <<RUBY
9
+ create_table :coins_paid_addresses do |t|
10
+ t.string :foreign_id, null: false
11
+ t.string :currency, null: false
12
+ t.string :address, null: false
13
+ t.string :tag
14
+ t.integer :external_id, null: false
15
+
16
+ t.timestamps
17
+ t.index [:foreign_id, :currency], unique: true
18
+ end
19
+ RUBY
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+ require 'rails/generators/active_record'
3
+ require_relative 'migration_data'
4
+
5
+ module CoinsPaid
6
+ module Generators
7
+ class MigrationGenerator < ActiveRecord::Generators::Base
8
+ argument :name, default: 'create_coins_paid_addresses'
9
+ source_root File.expand_path("templates", __dir__)
10
+
11
+ def copy_coins_paid_migration
12
+ migration_template 'migration.rb', "#{db_migrate_path}/#{file_name}.rb"
13
+ end
14
+
15
+ def migration_data
16
+ CoinsPaid::MigrationData.get
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Create<%= table_name.camelize %> < ActiveRecord::Migration[<%= ActiveRecord::Migration.current_version %>]
4
+ def change
5
+ <%= migration_data %>
6
+ end
7
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe CoinsPaid, '.address' do
4
+ let(:foreign_key) { 'user-id:2048' }
5
+ let(:currency) { 'BTC' }
6
+ let(:full_address_attributes) do
7
+ {
8
+ foreign_id: foreign_key,
9
+ currency: currency
10
+ }.merge(address_attributes)
11
+ end
12
+ let(:address_attributes) do
13
+ {
14
+ external_id: 1,
15
+ address: '12983h13ro1hrt24it432t',
16
+ tag: 'tag-123',
17
+ }
18
+ end
19
+ subject(:take_address) { described_class.address(foreign_key, currency: currency) }
20
+
21
+ context 'when there is existing record' do
22
+ let!(:address) do
23
+ CoinsPaid::CoinsPaidAddress.create!(full_address_attributes)
24
+ end
25
+
26
+ before do
27
+ allow(CoinsPaid::API).to receive(:take_address)
28
+ end
29
+
30
+ it 'returns existing record' do
31
+ expect(take_address).to eq address
32
+
33
+ expect(CoinsPaid::API).not_to have_received(:take_address)
34
+ end
35
+ end
36
+
37
+ context 'when coins paid api responds with error' do
38
+ before do
39
+ allow(CoinsPaid::API).to receive(:take_address).and_raise(CoinsPaid::API::Error)
40
+ end
41
+
42
+ it 'raises error' do
43
+ expect { take_address }.to raise_error(CoinsPaid::API::Error)
44
+ end
45
+ end
46
+
47
+ context 'when coins paid return valid response' do
48
+ before do
49
+ allow(CoinsPaid::API).to receive(:take_address).and_return(CoinsPaid::API::TakeAddress::Response.new(address_attributes))
50
+ end
51
+
52
+ it 'creates new address' do
53
+ expect(take_address).to have_attributes(full_address_attributes)
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe CoinsPaid, '.currency' do
4
+ let(:eth) { instance_double(CoinsPaid::API::Currency, currency: 'ETH') }
5
+
6
+ subject(:currency) { described_class.currency(eth.currency) }
7
+
8
+ context 'when CoinsPaid API responds correctly' do
9
+ before do
10
+ allow(CoinsPaid::API).to receive(:currencies_list) { currencies }
11
+ end
12
+
13
+ context 'and currency exists at CoinsPaid' do
14
+ let(:currencies) do
15
+ [eth, instance_double(CoinsPaid::API::Currency, currency: 'm' + eth.currency)]
16
+ end
17
+
18
+ it 'returns requested currency details' do
19
+ expect(currency).to eq eth
20
+ end
21
+ end
22
+
23
+ context 'and currency does not exist at CoinsPaid' do
24
+ let(:currencies) do
25
+ [instance_double(CoinsPaid::API::Currency, currency: 'm' + eth.currency)]
26
+ end
27
+
28
+ it 'errors' do
29
+ expect { currency }.to raise_error(CoinsPaid::UnknownCurrency)
30
+ end
31
+ end
32
+ end
33
+
34
+ context 'when coins paid api errors' do
35
+ before do
36
+ allow(CoinsPaid::API).to receive(:currencies_list).and_raise(CoinsPaid::API::Error)
37
+ end
38
+
39
+ it 're-raises error' do
40
+ expect { currency }.to raise_error(CoinsPaid::API::Error)
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe CoinsPaid, '.qr_code' do
4
+ let(:foreign_id) { 123 }
5
+ let(:coins_paid_address) do
6
+ instance_double CoinsPaid::CoinsPaidAddress,
7
+ currency: 'BTC',
8
+ address: 'abc123'
9
+ end
10
+ subject(:qr_code) do
11
+ described_class.qr_code(
12
+ foreign_id,
13
+ currency: 'BTC',
14
+ label: 'RedStar deposit',
15
+ message: 'Make a deposit to RedStar'
16
+ )
17
+ end
18
+
19
+ before do
20
+ allow(CoinsPaid).to receive(:address).with(foreign_id, currency: 'BTC').and_return(coins_paid_address)
21
+ end
22
+
23
+ describe '#payment_url' do
24
+ its(:url) { is_expected.to eq 'bitcoin:abc123?label=RedStar+deposit&message=Make+a+deposit+to+RedStar' }
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ ENV['COINS_PAID_CURRENCY'] = 'EUR'
2
+
3
+ if ENV['CIRCLE_ARTIFACTS']
4
+ require 'simplecov'
5
+ SimpleCov.start
6
+ end
7
+
8
+ require 'active_record'
9
+ require "active_record/railtie"
10
+ require 'rspec/rails'
11
+ require 'rspec/its'
12
+
13
+ require 'coins_paid_api'
14
+ require 'coins_paid_rails'
15
+
16
+ Dir['./spec/support/**/*.rb'].each { |f| require f }
17
+
18
+ ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: 'spec/test.db')
19
+
20
+ RSpec.configure do |config|
21
+ config.use_transactional_fixtures = true
22
+
23
+ config.before :suite do
24
+ CreateTable.migrate(:up)
25
+ end
26
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+ require_relative '../../../lib/generators/coins_paid/migration_data'
3
+
4
+ class CreateTable < ActiveRecord::Migration[ActiveRecord::Migration.current_version]
5
+ def up
6
+ drop_table :coins_paid_addresses if table_exists?(:coins_paid_addresses)
7
+
8
+ migration_data
9
+ end
10
+
11
+ def migration_data
12
+ instance_eval CoinsPaid::MigrationData.get
13
+ end
14
+ end
metadata ADDED
@@ -0,0 +1,132 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: coins_paid_rails
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Artem Biserov(artembiserov)
8
+ - Oleg Ivanov(morhekil)
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2019-11-20 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: coins_paid_api
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '1.0'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '1.0'
28
+ - !ruby/object:Gem::Dependency
29
+ name: activerecord
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: 4.2.0
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: 4.2.0
42
+ - !ruby/object:Gem::Dependency
43
+ name: dry-initializer
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: '3.0'
49
+ type: :runtime
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - "~>"
54
+ - !ruby/object:Gem::Version
55
+ version: '3.0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: dry-struct
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - "~>"
61
+ - !ruby/object:Gem::Version
62
+ version: '1.0'
63
+ type: :runtime
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '1.0'
70
+ - !ruby/object:Gem::Dependency
71
+ name: rspec-rails
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - "~>"
75
+ - !ruby/object:Gem::Version
76
+ version: '3.0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - "~>"
82
+ - !ruby/object:Gem::Version
83
+ version: '3.0'
84
+ description:
85
+ email:
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - ".circleci/config.yml"
91
+ - ".gitignore"
92
+ - ".rspec"
93
+ - Gemfile
94
+ - coins_paid_rails.gemspec
95
+ - lib/coins_paid.rb
96
+ - lib/coins_paid/address.rb
97
+ - lib/coins_paid/coins_paid_address.rb
98
+ - lib/coins_paid/qr_code.rb
99
+ - lib/coins_paid_rails.rb
100
+ - lib/generators/coins_paid/migration_data.rb
101
+ - lib/generators/coins_paid/migration_generator.rb
102
+ - lib/generators/coins_paid/templates/migration.rb
103
+ - spec/address_spec.rb
104
+ - spec/currency_spec.rb
105
+ - spec/qr_code_spec.rb
106
+ - spec/spec_helper.rb
107
+ - spec/support/database/create_table.rb
108
+ homepage:
109
+ licenses:
110
+ - MIT
111
+ metadata: {}
112
+ post_install_message:
113
+ rdoc_options: []
114
+ require_paths:
115
+ - lib
116
+ required_ruby_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ required_rubygems_version: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ requirements: []
127
+ rubyforge_project:
128
+ rubygems_version: 2.7.6
129
+ signing_key:
130
+ specification_version: 4
131
+ summary: CoinsPaid Rails Integration
132
+ test_files: []