krkt 0.1.1

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: d7ecf13d81e36dc2d9295da177be307c1cb561cdc58b724f08c5dce8b908c077
4
+ data.tar.gz: ec40bacfe8c616e1b7b87633e6f549c26879ea3362c3611b09c98b7046d4d90a
5
+ SHA512:
6
+ metadata.gz: 0b397260748d90b88bb7240f86b361c9e6f0f7faec26f13795e1edb279ae1375573d529b13b029df676e3b1eb791d22ffdd3017ba8280b7732194438384bd79c
7
+ data.tar.gz: 4f3aa178068ff860ae858c8e23d0bd3fe0010821297bf850ebbd46ad6cc7cb80499e14e8dd95038adf077480124db692e8105ffb3951b3fa2429d36efe1dfa2e
@@ -0,0 +1,8 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
@@ -0,0 +1,12 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.7
3
+ EnabledByDefault: true
4
+
5
+ Style/Copyright:
6
+ Enabled: false
7
+
8
+ Lint/ConstantResolution:
9
+ Enabled: false
10
+
11
+ Style/ConstantVisibility:
12
+ Enabled: false
@@ -0,0 +1,74 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, gender identity and expression, level of experience,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+ reported by contacting the project team at hernanirvaz@gmail.com. All
59
+ complaints will be reviewed and investigated and will result in a response that
60
+ is deemed necessary and appropriate to the circumstances. The project team is
61
+ obligated to maintain confidentiality with regard to the reporter of an incident.
62
+ Further details of specific enforcement policies may be posted separately.
63
+
64
+ Project maintainers who do not follow or enforce the Code of Conduct in good
65
+ faith may face temporary or permanent repercussions as determined by other
66
+ members of the project's leadership.
67
+
68
+ ## Attribution
69
+
70
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
+ available at [https://contributor-covenant.org/version/1/4][version]
72
+
73
+ [homepage]: https://contributor-covenant.org
74
+ [version]: https://contributor-covenant.org/version/1/4/
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ source('https://rubygems.org')
4
+
5
+ # Specify your gem's dependencies in krkt.gemspec
6
+ gemspec
7
+
8
+ # Make-like program implemented in Ruby.
9
+ gem('rake', '~> 12.0')
@@ -0,0 +1,83 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ krkt (0.1.1)
5
+ curb
6
+ faraday
7
+ google-cloud-bigquery
8
+ json
9
+ thor
10
+ yard
11
+
12
+ GEM
13
+ remote: https://rubygems.org/
14
+ specs:
15
+ addressable (2.7.0)
16
+ public_suffix (>= 2.0.2, < 5.0)
17
+ concurrent-ruby (1.1.7)
18
+ curb (0.9.10)
19
+ declarative (0.0.20)
20
+ declarative-option (0.1.0)
21
+ faraday (1.0.1)
22
+ multipart-post (>= 1.2, < 3)
23
+ google-api-client (0.44.0)
24
+ addressable (~> 2.5, >= 2.5.1)
25
+ googleauth (~> 0.9)
26
+ httpclient (>= 2.8.1, < 3.0)
27
+ mini_mime (~> 1.0)
28
+ representable (~> 3.0)
29
+ retriable (>= 2.0, < 4.0)
30
+ signet (~> 0.12)
31
+ google-cloud-bigquery (1.21.2)
32
+ concurrent-ruby (~> 1.0)
33
+ google-api-client (~> 0.33)
34
+ google-cloud-core (~> 1.2)
35
+ googleauth (~> 0.9)
36
+ mini_mime (~> 1.0)
37
+ google-cloud-core (1.5.0)
38
+ google-cloud-env (~> 1.0)
39
+ google-cloud-errors (~> 1.0)
40
+ google-cloud-env (1.3.3)
41
+ faraday (>= 0.17.3, < 2.0)
42
+ google-cloud-errors (1.0.1)
43
+ googleauth (0.13.1)
44
+ faraday (>= 0.17.3, < 2.0)
45
+ jwt (>= 1.4, < 3.0)
46
+ memoist (~> 0.16)
47
+ multi_json (~> 1.11)
48
+ os (>= 0.9, < 2.0)
49
+ signet (~> 0.14)
50
+ httpclient (2.8.3)
51
+ json (2.3.1)
52
+ jwt (2.2.2)
53
+ memoist (0.16.2)
54
+ mini_mime (1.0.2)
55
+ multi_json (1.15.0)
56
+ multipart-post (2.1.1)
57
+ os (1.1.1)
58
+ public_suffix (4.0.5)
59
+ rake (12.3.3)
60
+ representable (3.0.4)
61
+ declarative (< 0.1.0)
62
+ declarative-option (< 0.2.0)
63
+ uber (< 0.2.0)
64
+ retriable (3.1.2)
65
+ signet (0.14.0)
66
+ addressable (~> 2.3)
67
+ faraday (>= 0.17.3, < 2.0)
68
+ jwt (>= 1.5, < 3.0)
69
+ multi_json (~> 1.10)
70
+ thor (1.0.1)
71
+ uber (0.1.0)
72
+ yard (0.9.25)
73
+
74
+ PLATFORMS
75
+ ruby
76
+
77
+ DEPENDENCIES
78
+ bundler
79
+ krkt!
80
+ rake (~> 12.0)
81
+
82
+ BUNDLED WITH
83
+ 2.1.4
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2020 Hernâni Rodrigues Vaz
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,42 @@
1
+ # Krkt
2
+
3
+ Arquiva transactions kraken no bigquery. Pode ajustar dias para reposicionamento temporal.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'krkt'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle install
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install krkt
20
+
21
+ ## Usage
22
+
23
+ TODO: Write usage instructions here
24
+
25
+ ## Development
26
+
27
+ After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
28
+
29
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
30
+
31
+ ## Contributing
32
+
33
+ Bug reports and pull requests are welcome on GitHub at https://github.com/hernanirvaz/krkt. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/hernanirvaz/krkt/blob/master/CODE_OF_CONDUCT.md).
34
+
35
+
36
+ ## License
37
+
38
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
39
+
40
+ ## Code of Conduct
41
+
42
+ Everyone interacting in the Krkt project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/hernanirvaz/krkt/blob/master/CODE_OF_CONDUCT.md).
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+ task :default => :spec
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "krkt"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require('krkt')
5
+
6
+ Krkt::CLI.start(ARGV)
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative('lib/krkt/version')
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'krkt'
7
+ spec.version = Krkt::VERSION
8
+ spec.authors = ['Hernâni Rodrigues Vaz']
9
+ spec.email = ['hernanirvaz@gmail.com']
10
+
11
+ spec.summary = 'Arquiva transactions kraken no bigquery.'
12
+ spec.description = "#{spec.summary} Pode ajustar dias para reposicionamento temporal."
13
+ spec.homepage = 'https://github.com/hernanirvaz/krkt'
14
+ spec.license = 'MIT'
15
+ spec.required_ruby_version = Gem::Requirement.new('>= 2.3.0')
16
+
17
+ spec.metadata['yard.run'] = 'yard'
18
+ spec.metadata['homepage_uri'] = spec.homepage
19
+
20
+ # Specify which files should be added to the gem when it is released.
21
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
22
+ spec.files =
23
+ Dir.chdir(File.expand_path(__dir__)) do
24
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
25
+ end
26
+ spec.bindir = 'exe'
27
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
+ spec.require_paths = ['lib']
29
+
30
+ spec.add_development_dependency('bundler')
31
+ spec.add_development_dependency('rake')
32
+
33
+ spec.add_dependency('curb')
34
+ spec.add_dependency('faraday')
35
+ spec.add_dependency('google-cloud-bigquery')
36
+ spec.add_dependency('json')
37
+ spec.add_dependency('thor')
38
+ spec.add_dependency('yard')
39
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require('thor')
4
+ require('krkt/bigquery')
5
+ require('krkt/client')
6
+ require('krkt/kraken')
7
+ require('krkt/version')
8
+
9
+ module Krkt
10
+ class Error < ::StandardError; end
11
+
12
+ # classe para carregar/mostrar dados comuns bigquery & etherscan
13
+ class CLI < Thor
14
+ desc 'work', 'carrega transacoes novas no bigquery'
15
+ option :h, type: :hash, default: {}, desc: 'configuracao ajuste reposicionamento temporal'
16
+ # carrega transacoes novas no bigquery
17
+ def work
18
+ Bigquery.new(options).processa
19
+ end
20
+
21
+ desc 'show', 'mostra resumo saldos & transacoes'
22
+ option :v, type: :boolean, default: false, desc: 'mostra transacoes'
23
+ option :t, type: :boolean, default: false, desc: 'mostra transacoes todas ou somente novas'
24
+ # mostra resumo saldos & transacoes
25
+ def show
26
+ Bigquery.new(options).transacoes.mostra_resumo
27
+ end
28
+
29
+ desc 'novo', 'mostra reumo carteiras & transacoes'
30
+ # mostra reumo carteiras & transacoes
31
+ def novo
32
+ client = Client.new
33
+ p(client.trades_history(start: 'TLADFV-QIUTN-QDNCBR')['trades'].keys)
34
+ # p(client.ledgers(start: 'L4ZDDO-WUGC2-Z72VPW')['ledger'].keys)
35
+ p(client.balance)
36
+ end
37
+
38
+ default_task :show
39
+ end
40
+ end
@@ -0,0 +1,126 @@
1
+ # frozen_string_literal: true
2
+
3
+ require('google/cloud/bigquery')
4
+ require('bigdecimal/util')
5
+
6
+ # @author Hernani Rodrigues Vaz
7
+ module Krkt
8
+ BD = 'hernanirvaz.coins'
9
+
10
+ # classe para processar kraken & bigquery
11
+ class Bigquery
12
+ # @return [Google::Cloud::Bigquery] API bigquery
13
+ attr_reader :api
14
+ # @return [Google::Cloud::Bigquery::QueryJob] job bigquery
15
+ attr_reader :job
16
+ # @return [Thor::CoreExt::HashWithIndifferentAccess] opcoes trabalho
17
+ attr_reader :ops
18
+ # @return (see sql)
19
+ attr_reader :sqr
20
+
21
+ # @param [Thor::CoreExt::HashWithIndifferentAccess] pop opcoes trabalho
22
+ # @option pop [Hash] :h ({}) configuracao ajuste reposicionamento temporal
23
+ # @option pop [Boolean] :v (false) mostra transacoes normais & ledger?
24
+ # @option pop [Boolean] :t (false) mostra transacoes todas ou somente novas?
25
+ # @return [Bigquery] API bigquery & API kraken
26
+ def initialize(pop)
27
+ # usa env GOOGLE_APPLICATION_CREDENTIALS para obter credentials
28
+ # @see https://cloud.google.com/bigquery/docs/authentication/getting-started
29
+ @api = Google::Cloud::Bigquery.new
30
+ @ops = pop
31
+ end
32
+
33
+ # @return [Kraken] API kraken - processar transacoes normais e ledgers
34
+ def transacoes
35
+ @transacoes ||= Kraken.new(
36
+ {
37
+ sl: sql("select * from #{BD}.ussl")[0],
38
+ nt: sql("select * from #{BD}.ustx order by time,txid"),
39
+ nl: sql("select * from #{BD}.uslx order by time,txid")
40
+ },
41
+ ops
42
+ )
43
+ end
44
+
45
+ # insere transacoes novas nas tabelas ust (trades), usl (ledger)
46
+ def processa
47
+ puts(format("%<n>2i TRADES INSERIDAS #{BD}.ust", n: transacoes.trades.count.positive? ? dml(ust_ins) : 0))
48
+ puts(format("%<n>2i LEDGER INSERIDAS #{BD}.usl", n: transacoes.ledger.count.positive? ? dml(usl_ins) : 0))
49
+ end
50
+
51
+ # @return [String] comando insert SQL formatado ust (trades)
52
+ def ust_ins
53
+ "insert #{BD}.ust(txid,ordertxid,pair,time,type,ordertype,price,cost,fee,vol,margin,misc,ledgers,dias" \
54
+ ") VALUES#{transacoes.trades.map { |k, v| ust_val1(k, v) }.join(',')}"
55
+ end
56
+
57
+ # @return [String] valores formatados ust (trades parte1)
58
+ def ust_val1(idx, hes)
59
+ "('#{idx}'," \
60
+ "'#{hes['ordertxid']}'," \
61
+ "'#{hes['pair']}'," \
62
+ "PARSE_DATETIME('%s', '#{String(hes['time'].round)}')," \
63
+ "'#{hes['type']}'," \
64
+ "'#{hes['ordertype']}'," \
65
+ "cast(#{hes['price']} as numeric)," \
66
+ "cast(#{hes['cost']} as numeric)," \
67
+ "cast(#{hes['fee']} as numeric)," \
68
+ "#{ust_val2(idx, hes)}"
69
+ end
70
+
71
+ # @return [String] valores formatados ust (trades parte2)
72
+ def ust_val2(idx, hes)
73
+ "cast(#{hes['vol']} as numeric)," \
74
+ "cast(#{hes['margin']} as numeric)," \
75
+ "#{hes['misc'].length.zero? ? 'null' : "'#{hes['misc']}'"}," \
76
+ "'#{transacoes.ledger.select { |_, v| v['refid'] == idx }.keys.join(',') || ''}'," \
77
+ "#{Integer(ops[:h][idx] || 0)})"
78
+ end
79
+
80
+ # @return [String] comando insert SQL formatado usl (ledger)
81
+ def usl_ins
82
+ "insert #{BD}.usl(txid,refid,time,type,aclass,asset,amount,fee" \
83
+ ") VALUES#{transacoes.ledger.map { |k, v| usl_val1(k, v) }.join(',')}"
84
+ end
85
+
86
+ # @return [String] valores formatados usl (ledger parte1)
87
+ def usl_val1(idx, hes)
88
+ "('#{idx}'," \
89
+ "'#{hes['refid']}'," \
90
+ "PARSE_DATETIME('%s', '#{String(hes['time'].round)}')," \
91
+ "'#{hes['type']}'," \
92
+ "#{hes['aclass'].length.zero? ? 'null' : "'#{hes['aclass']}'"}," \
93
+ "'#{hes['asset']}'," \
94
+ "cast(#{hes['amount']} as numeric)," \
95
+ "cast(#{hes['fee']} as numeric))"
96
+ end
97
+
98
+ # cria job bigquery & verifica execucao
99
+ #
100
+ # @param cmd (see sql)
101
+ # @return [Boolean] job ok?
102
+ def job?(cmd)
103
+ @job = api.query_job(cmd)
104
+ @job.wait_until_done!
105
+ puts(@job.error['message']) if @job.failed?
106
+ @job.failed?
107
+ end
108
+
109
+ # cria Structured Query Language (SQL) job bigquery
110
+ #
111
+ # @param [String] cmd comando SQL a executar
112
+ # @param [String] red resultado quando SQL tem erro
113
+ # @return [Google::Cloud::Bigquery::Data] resultado do SQL
114
+ def sql(cmd, red = [])
115
+ @sqr = job?(cmd) ? red : job.data
116
+ end
117
+
118
+ # cria Data Manipulation Language (DML) job bigquery
119
+ #
120
+ # @param cmd (see sql)
121
+ # @return [Integer] numero linhas afetadas
122
+ def dml(cmd)
123
+ job?(cmd) ? 0 : job.num_dml_affected_rows
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,443 @@
1
+ # frozen_string_literal: true
2
+
3
+ require('openssl')
4
+ require('base64')
5
+ require('curb')
6
+ require('json')
7
+
8
+ module Krkt
9
+ # class Client
10
+ class Client
11
+ # @return [String] API key
12
+ attr_reader :key
13
+ # @return [String] API secret
14
+ attr_reader :sec
15
+ # @return [String] API public url
16
+ attr_reader :puu
17
+ # @return [String] API private url
18
+ attr_reader :pru
19
+ # @return [String] API private path
20
+ attr_reader :pth
21
+
22
+ # def initialize(api_key: nil, api_secret: nil, options: {})
23
+ def initialize(api_key: ENV['KRAKEN_API_KEY'], api_secret: ENV['KRAKEN_API_SECRET'], options: {})
24
+ b = options.fetch(:base_uri, 'https://api.kraken.com')
25
+ v = options.fetch(:version, 0)
26
+ @key = api_key
27
+ @sec = api_secret
28
+ @puu = "#{b}/#{v}/public/"
29
+ @pru = "#{b}/#{v}/private/"
30
+ @pth = "/#{v}/private/"
31
+ end
32
+
33
+ # type = type of trade (optional)
34
+ # all = all types (default)
35
+ # any position = any position (open or closed)
36
+ # closed position = positions that have been closed
37
+ # closing position = any trade closing all or part of a position
38
+ # no position = non-positional trades
39
+ # trades = whether or not to include trades related to position in output (optional. default = false)
40
+ # start = starting unix timestamp or trade tx id of results (optional. exclusive)
41
+ # end = ending unix timestamp or trade tx id of results (optional. inclusive)
42
+ # ofs = result offset
43
+ # Result: array of trade info
44
+ # trades = array of trade info with txid as the key
45
+ # ordertxid = order responsible for execution of trade
46
+ # pair = asset pair
47
+ # time = unix timestamp of trade
48
+ # type = type of order (buy/sell)
49
+ # ordertype = order type
50
+ # price = average price order was executed at (quote currency)
51
+ # cost = total cost of order (quote currency)
52
+ # fee = total fee (quote currency)
53
+ # vol = volume (base currency)
54
+ # margin = initial margin (quote currency)
55
+ # misc = comma delimited list of miscellaneous info
56
+ # closing = trade closes all or part of a position
57
+ # count = amount of available trades info matching criteria
58
+ def trades_history(**opts)
59
+ post_private('TradesHistory', **opts)['result']
60
+ end
61
+
62
+ # def ledgers
63
+ def ledgers(**opts)
64
+ post_private('Ledgers', **opts)['result']
65
+ end
66
+
67
+ # def balance
68
+ def balance
69
+ post_private('Balance')['result']
70
+ end
71
+
72
+ # Get server time
73
+ # URL: https://api.kraken.com/0/public/Time
74
+ # Returns a hash with keys +error+ and +result+.
75
+ # +result+ is an array of hashes with keys:
76
+ # +unixtime+ = unix timestamp
77
+ # +rfc1123+ = RFC 1123 time format
78
+ #
79
+ def server_time
80
+ get_public('Time')
81
+ end
82
+
83
+ private
84
+
85
+ # HTTP GET request for public API queries.
86
+ def get_public(method, **opts)
87
+ parse_response(Curl.get("#{puu}#{method}", opts))
88
+ end
89
+
90
+ # HTTP POST request for private API queries involving user credentials.
91
+ def post_private(method, **opts)
92
+ # Generate a continually-increasing unsigned 51-bit integer nonce from the current Unix Time.
93
+ t = opts.merge!({ nonce: Integer(Time.now.to_f * 1_000_000) }).map { |p| p.join('=') }.join('&')
94
+
95
+ parse_response(Curl.post("#{pru}#{method}", t) do |r|
96
+ r.headers = {
97
+ 'api-key': key,
98
+ 'api-sign': authenticate(method, opts[:nonce], t)
99
+ }
100
+ end)
101
+ end
102
+
103
+ def authenticate(method, nonce, params)
104
+ raise(ArgumentError, 'API Key is not set') unless key
105
+ raise(ArgumentError, 'API Secret is not set') unless sec
106
+
107
+ Base64.strict_encode64(OpenSSL::HMAC.digest(
108
+ 'sha512',
109
+ Base64.decode64(sec),
110
+ "#{pth}#{method}#{Digest::SHA256.digest("#{nonce}#{params}")}"
111
+ ))
112
+ end
113
+
114
+ def parse_response(http)
115
+ # HTTP_SUCCESS = 200
116
+ http.response_code == 200 ? JSON.parse(http.body) : http.status
117
+ rescue JSON::ParserError,
118
+ EOFError,
119
+ Errno::ECONNRESET,
120
+ Errno::EINVAL,
121
+ Net::HTTPBadResponse,
122
+ Net::HTTPHeaderSyntaxError,
123
+ Net::ProtocolError,
124
+ Timeout::Error => e
125
+ "Erro da API #{e.inspect}"
126
+ end
127
+ end
128
+ end
129
+
130
+ # Get asset info
131
+ # URL: https://api.kraken.com/0/public/Assets
132
+ # Input:
133
+ # +asset+ = a comma-delimited, case-insensitive asset list string
134
+ # (optional, defaults to all assets).
135
+ # +aclass+ = asset class (optional, defaults to +currency+).
136
+ # Not useful for now; all assets have same value 'currency'.
137
+ #
138
+ # Returns a hash with keys +error+ and +result+.
139
+ # +result+ is a hash of assets with keys like ZEUR, ZUSD, XXBT, etc.
140
+ # Each asset is an array of the asset name and an info hash containing:
141
+ # +altname+ = alternate name, like EUR, USD, XBT, etc.
142
+ # +aclass+ = asset class (for now are all set to 'currency').
143
+ # +decimals+ = decimal places for record keeping.
144
+ # +display_decimals+ = decimal places for display (usually fewer).
145
+ #
146
+ # def assets(assets = nil)
147
+ # if assets
148
+ # get_public('Assets', asset: assets)
149
+ # else
150
+ # get_public('Assets')
151
+ # end
152
+ # end
153
+
154
+ # Get tradable asset pairs
155
+ # URL: https://api.kraken.com/0/public/AssetPairs
156
+ # Input:
157
+ # +pair+ = a comma-delimited, case-insensitive list of asset pairs
158
+ # (optional, defaults to all asset pairs).
159
+ # +info+ = info to retrieve (optional, defaults to all info).
160
+ # Options:
161
+ # +leverage+ = leverage info
162
+ # +fees+ = fees schedule
163
+ # +margin+ = margin info
164
+ #
165
+ # Returns a hash with keys +error+ and +result+.
166
+ # +result+ is a hash of asset pairs with keys like XXBTZEUR and XXBTZUSD.
167
+ # Each asset pair is an array of the name and a hash containing:
168
+ # +altname+ = alternate name, like EUR, USD, XBT, etc.
169
+ # +aclass_base+ = asset class of base component
170
+ # +base+ = asset id of base component
171
+ # +aclass_quote+ = asset class of quote component
172
+ # +quote+ = asset id of quote component
173
+ # +lot+ = volume lot size
174
+ # +pair_decimals+ = scaling decimal places for pair
175
+ # +lot_decimals+ = scaling decimal places for volume
176
+ # +lot_multiplier+ = amount to multiply lot volume by to get
177
+ # currency volume
178
+ # +leverage_buy+ = array of leverages available when buying
179
+ # +leverage_sell+ = array of leverages available when selling
180
+ # +fees+ = fee schedule array in
181
+ # [volume, percent fee] tuples
182
+ # +fees_maker+ = maker fee schedule array in
183
+ # [volume, percent fee] tuples if on maker/taker
184
+ # +fee_volume_currency+ = volume discount currency
185
+ # +margin_call+ = margin call level
186
+ # +margin_stop+ = stop-out/liquidation margin level
187
+ #
188
+ # def asset_pairs(pairs = nil)
189
+ # if pairs
190
+ # get_public('AssetPairs', pair: pairs)
191
+ # else
192
+ # get_public('AssetPairs')
193
+ # end
194
+ # end
195
+
196
+ # def ticker(pairs = nil)
197
+ # def ticker(pairs = nil)
198
+ # get_public('Ticker', pair: pairs)
199
+ # end
200
+
201
+ # Get OHLC (Open, High, Low, Close) data
202
+ # URL: https://api.kraken.com/0/public/OHLC
203
+ # Input:
204
+ # +pair+ = required asset pair for which to query OHLC data
205
+ # +interval+ = optional time frame interval in minutes. Defaults to 1.
206
+ # Permitted values: 1, 5, 15, 30, 60, 240, 1440, 10080, 21600
207
+ # Returns an Invalid Arguments error for other values.
208
+ # +since+ = optional Unix Time from when to return committed OHLC data
209
+ #
210
+ # Returns a hash with keys `error' and `result'.
211
+ # +result+ is an array containing pair name, OHLC data, and last Unixtime.
212
+ # The OHLC data array contains:
213
+ # time, open, high, low, close, VWAP, price, volume, count.
214
+ # The last entry in the OHLC data array is for the current, not-yet-
215
+ # committed frame and is always present, regardless of the value of since.
216
+ # +last+ is to be used as `since' when getting new committed OHLC data.
217
+ #
218
+ # def ohlc(pair = nil, interval: 1, since: nil)
219
+ # get_public('OHLC', pair: pair, interval: interval, since: since)
220
+ # end
221
+ # def order_book(pair = nil)
222
+ # get_public('Depth', pair: pair)
223
+ # end
224
+ # def trades(pair, since = nil)
225
+ # get_public('Trades', pair: pair, since: since)
226
+ # end
227
+ # def spread(pair = nil, opts = {})
228
+ # opts['pair'] = pair
229
+ # get_public('Spread', opts)
230
+ # end
231
+
232
+ # Create a new order (POST)
233
+ # URL: https://api.kraken.com/0/private/AddOrder
234
+ # Input:
235
+ # +pair+ required asset pair, example: XBTEUR
236
+ # +type+ required operation type, possible values: buy/sell
237
+ # +volume+ required order size
238
+ # +ordertype+ required, possible values:
239
+ # market
240
+ # limit price = limit price
241
+ # stop-loss price = stop loss price
242
+ # take-profit price = take profit price
243
+ # stop-loss-profit price = stop loss price,
244
+ # price2 = take profit price)
245
+ # stop-loss-profit-limit price = stop loss price,
246
+ # price2 = take profit price
247
+ # stop-loss-limit price = stop loss trigger price,
248
+ # price2 = triggered limit price
249
+ # take-profit-limit price = take profit trigger price,
250
+ # price2 = triggered limit price
251
+ # trailing-stop price = trailing stop offset
252
+ # trailing-stop-limit price = trailing stop offset,
253
+ # price2 = triggered limit offset
254
+ # stop-loss-and-limit price = stop loss price
255
+ # price2 = limit price
256
+ # settle-position
257
+ # +price+ price (optional, dependant on ordertype)
258
+ # +price2+ secondary price (optional, dependent on ordertype)
259
+ # +leverage+ amount of leverage desired (optional, default = none)
260
+ #
261
+ # Examples:
262
+ #
263
+ # require 'kraken_ruby_client'
264
+ # client = Kraken::Client.new(api_key: YOUR_KEY, api_secret: YOUR_SECRET)
265
+ #
266
+ # Market buy order:
267
+ #
268
+ # client.add_order(pair: 'XBTEUR', type: 'buy', ordertype: 'market',
269
+ # volume: 0.5)
270
+ #
271
+ # Limit buy order:
272
+ #
273
+ # client.add_order(pair: 'XBTUSD', type: 'buy', ordertype: 'limit',
274
+ # volume: 1.25, price: 5000)
275
+ #
276
+ # Margin sell order (short):
277
+ #
278
+ # client.add_order(pair: 'DASHEUR', type: 'sell', ordertype: 'market',
279
+ # volume: 1, leverage: 2)
280
+ #
281
+ # def add_order(opts = {})
282
+ # missing_args = add_order_required_args - opts.keys.map(&:to_s)
283
+ # raise(ArgumentError, add_order_err_msg(missing_args)) if missing_args.any?
284
+ # post_private('AddOrder', opts)
285
+ # end
286
+
287
+ # def add_order_required_args
288
+ # %w[pair type volume ordertype].freeze
289
+ # end
290
+
291
+ # def add_order_err_msg(missing_args)
292
+ # "the following required arguments are missing: #{missing_args.join(', ')}"
293
+ # end
294
+
295
+ # Cancel order having txn id
296
+ #
297
+ # def cancel_order(txid)
298
+ # post_private('CancelOrder', txid: txid)
299
+ # end
300
+
301
+ # Fetch trade volume (POST)
302
+ # URL: https://api.kraken.com/0/private/TradeVolume
303
+ # Input:
304
+ # +pair+ [string] comma-delimited list of asset pairs (optional)
305
+ # +fee-info+ [boolean] whether or not to include fee info (optional)
306
+ #
307
+ # Returns a hash with keys `error' and `result'.
308
+ # +result+ is a hash of hashes containing keys:
309
+ # currency, volume, fees, fees_maker.
310
+ # currency = volume currency
311
+ # volume = current discount volume
312
+ # fees = array of asset pairs and fee tier info (if requested)
313
+ # fee = current fee in percent
314
+ # minfee = minimum fee for pair (if not fixed fee)
315
+ # maxfee = maximum fee for pair (if not fixed fee)
316
+ # nextfee = next tier's fee for pair
317
+ # (if not fixed fee. nil if at lowest fee tier)
318
+ # nextvolume = volume level of next tier
319
+ # (if not fixed fee. nil if at lowest fee tier)
320
+ # tiervolume = volume level of current tier
321
+ # (if not fixed fee. nil if at lowest fee tier)
322
+ # fees_maker = array of asset pairs and maker fee tier info (if requested)
323
+ # for any pairs on maker/taker schedule
324
+ # fee = current fee in percent
325
+ # minfee = minimum fee for pair (if not fixed fee)
326
+ # maxfee = maximum fee for pair (if not fixed fee)
327
+ # nextfee = next tier's fee for pair
328
+ # (if not fixed fee, nil if at lowest fee tier)
329
+ # nextvolume = volume level of next tier
330
+ # (if not fixed fee, nil if at lowest fee tier)
331
+ # tiervolume = volume level of current tier
332
+ # (if not fixed fee, nil if at lowest fee tier)
333
+ #
334
+ # Note: If an asset pair is on a maker/taker fee schedule, the taker side is
335
+ # given in "fees" and maker side in "fees_maker". For pairs not on
336
+ # maker/taker, they will only be given in "fees".
337
+ #
338
+ # Examples:
339
+ #
340
+ # require 'kraken_ruby_client'
341
+ # client = Kraken::Client.new(api_key: YOUR_KEY, api_secret: YOUR_SECRET)
342
+ # client.trade_volume
343
+ # client.trade_volume(pair: 'XBTEUR, etcusd, xbteth')
344
+ # client.trade_volume(pair: 'XBTEUR', 'fee-info': true)
345
+ #
346
+ # def trade_volume(opts = {})
347
+ # post_private('TradeVolume', opts)
348
+ # end
349
+
350
+ # Fetch open orders (POST)
351
+ # URL: https://api.kraken.com/0/private/OpenOrders
352
+ # Input:
353
+ # +trades+ predicate to include trades (optional, default `false`)
354
+ # +userref+ restrict results to given user reference id (optional)
355
+ #
356
+ # Examples:
357
+ #
358
+ # require 'kraken_ruby_client'
359
+ # client = Kraken::Client.new(api_key: YOUR_KEY, api_secret: YOUR_SECRET)
360
+ # open_orders = client.open_orders.dig('result', 'open')
361
+ #
362
+ # Display all open orders from newest to oldest:
363
+ #
364
+ # open_orders.each { |o| puts "#{o.first}, #{o.last.dig('descr')}" }
365
+ #
366
+ # Display all open orders by descending price:
367
+ #
368
+ # open_orders
369
+ # .sort_by { |o| o.last.dig('descr', 'price').to_i }
370
+ # .reverse
371
+ # .each { |o| puts "#{o.first}, #{o.last.dig('descr')}" }
372
+ #
373
+ # Return most recent open order and total number of open orders:
374
+ #
375
+ # open_orders.first
376
+ # open_orders.count
377
+ #
378
+ # Return all open orders for a pair:
379
+ #
380
+ # pair = 'ETHEUR'
381
+ # open_orders.select { |_, v| v.dig('descr', 'pair') == pair }
382
+ #
383
+ # Return most recent open order for a pair:
384
+ #
385
+ # open_orders.detect { |_, v| v.dig('descr', 'pair') == pair }
386
+ #
387
+ # def open_orders(opts = {})
388
+ # post_private('OpenOrders', opts)
389
+ # end
390
+
391
+ # Fetch closed orders (POST)
392
+ # URL: https://api.kraken.com/0/private/ClosedOrders
393
+ # Input:
394
+ # +trades+ predicate to include trades (optional, default `false`)
395
+ # +userref+ restrict results to given user reference id (optional)
396
+ # +start+ start UNIX timestamp or order txid (optional. exclusive)
397
+ # +end+ end UNIX timestamp or order txid (optional. inclusive)
398
+ # +ofs+ result offset
399
+ # +closetime+ which time to use, optional: open, close, or both (default)
400
+ # Note: Times given by order txids are more accurate than UNIX timestamps.
401
+ # If an order txid is given, the order's open time is used.
402
+ #
403
+ # Examples:
404
+ #
405
+ # require 'kraken_ruby_client'
406
+ # client = Kraken::Client.new(api_key: YOUR_KEY, api_secret: YOUR_SECRET)
407
+ # closed_orders = client.closed_orders.dig('result', 'closed')
408
+ #
409
+ # Return most recent closed order and total number of closed orders:
410
+ #
411
+ # closed_orders.first
412
+ # closed_orders.count
413
+ #
414
+ # Return all closed orders for a pair:
415
+ #
416
+ # pair = 'ZECEUR'
417
+ # closed_orders.select { |_, v| v.dig('descr', 'pair') == pair }
418
+ #
419
+ # Return most recent closed order for a pair:
420
+ #
421
+ # closed_orders.detect { |_, v| v.dig('descr', 'pair') == pair }
422
+ #
423
+ # def closed_orders(opts = {})
424
+ # post_private('ClosedOrders', opts)
425
+ # end
426
+
427
+ # Withdraw funds (POST)
428
+ # URL: https://api.kraken.com/0/private/Withdraw
429
+ # Input:
430
+ # +aclass+ asset class (optional)
431
+ # +asset+ asset being withdrawn
432
+ # +key+ withdrawal key name, as set up on your account
433
+ # +amount+ amount to withdraw, including fees
434
+ #
435
+ # Examples:
436
+ #
437
+ # require 'kraken_ruby_client'
438
+ # client = Kraken::Client.new(api_key: YOUR_KEY, api_secret: YOUR_SECRET)
439
+ # withdrawal = client.withdraw(asset: 'USD', key: YOUR_KEY, amount: 20.0)
440
+ #
441
+ # def withdraw(opts = {})
442
+ # post_private('Withdraw', opts)
443
+ # end
@@ -0,0 +1,125 @@
1
+ # frozen_string_literal: true
2
+
3
+ require('bigdecimal/util')
4
+
5
+ # @author Hernani Rodrigues Vaz
6
+ module Krkt
7
+ # classe para processar carteiras & transacoes normais e ledgers
8
+ class Kraken
9
+ # @return [Client] API kraken
10
+ attr_reader :api
11
+ # @return [Array<Hash>] todos os dados bigquery
12
+ attr_reader :dbq
13
+ # @return [Thor::CoreExt::HashWithIndifferentAccess] opcoes trabalho
14
+ attr_reader :ops
15
+
16
+ # @param [Hash] dad todos os dados bigquery
17
+ # @param [Thor::CoreExt::HashWithIndifferentAccess] pop opcoes trabalho
18
+ # @option pop [Hash] :h ({}) configuracao dias ajuste reposicionamento temporal
19
+ # @option pop [Boolean] :v (false) mostra dados transacoes normais & ledgers?
20
+ # @return [Kraken] API kraken - processar transacoes normais e ledgers
21
+ def initialize(dad, pop)
22
+ @api = Client.new
23
+ @dbq = dad
24
+ @ops = pop
25
+ end
26
+
27
+ # @return [Array<Hash>] todos os dados kraken - saldos & transacoes
28
+ def dkr
29
+ @dkr ||= {
30
+ sl: api.balance,
31
+ kt: api.trades_history,
32
+ kl: api.ledgers
33
+ }
34
+ end
35
+
36
+ # @return [Array<Integer>] lista blocknumbers de transacoes normais
37
+ def kyt
38
+ @kyt ||= dkr[:kt]['trades'].keys - (ops[:t] ? [] : dbq[:nt].map { |e| e[:txid] })
39
+ end
40
+
41
+ # @return [Array<Integer>] lista blocknumbers de transacoes ledger
42
+ def kyl
43
+ @kyl ||= dkr[:kl]['ledger'].keys - (ops[:t] ? [] : dbq[:nl].map { |e| e[:txid] })
44
+ end
45
+
46
+ # @return [Array<Hash>] lista transacoes novas trades
47
+ def trades
48
+ @trades ||= dkr[:kt]['trades'].select { |k, _| kyt.include?(k) }
49
+ end
50
+
51
+ # @return [Array<Hash>] lista transacoes novas ledger
52
+ def ledger
53
+ @ledger ||= dkr[:kl]['ledger'].select { |k, _| kyl.include?(k) }
54
+ end
55
+
56
+ # def formata_saldos(moe, sal)
57
+ def formata_saldos(moe, sal)
58
+ t = dbq[:sl][moe.downcase.to_sym].to_d
59
+ format(
60
+ '%<mo>-5.5s %<kr>21.9f %<bq>21.9f %<ok>3.3s',
61
+ mo: moe,
62
+ kr: sal,
63
+ bq: t,
64
+ ok: t == sal ? 'OK' : 'NOK'
65
+ )
66
+ end
67
+
68
+ # @parm [Hash] htx transacao normal
69
+ # @return [String] texto formatado transacao normal
70
+ def formata_transacao_trades(idx, htx)
71
+ format(
72
+ '%<ky>-6.6s %<dt>19.19s %<ty>-10.10s %<mo>-8.8s %<pr>8.2f %<vl>15.7f %<co>8.2f',
73
+ ky: idx,
74
+ dt: Time.at(htx['time']),
75
+ ty: "#{htx['type']}/#{htx['ordertype']}",
76
+ mo: htx['pair'],
77
+ pr: htx['price'].to_d,
78
+ vl: htx['vol'].to_d,
79
+ co: htx['cost'].to_d
80
+ )
81
+ end
82
+
83
+ # @parm [Hash] hlx transacao ledger
84
+ # @return [String] texto formatado transacao ledger
85
+ def formata_transacao_ledger(idx, hlx)
86
+ format(
87
+ '%<ky>-6.6s %<dt>19.19s %<ty>-10.10s %<mo>-4.4s %<pr>18.7f %<vl>18.7f',
88
+ ky: idx,
89
+ dt: Time.at(hlx['time']),
90
+ ty: hlx['type'],
91
+ mo: hlx['asset'],
92
+ pr: hlx['amount'].to_d,
93
+ vl: hlx['fee'].to_d
94
+ )
95
+ end
96
+
97
+ # @return [String] texto saldos & transacoes & ajuste dias
98
+ def mostra_resumo
99
+ puts("\nmoeda saldo bigquery saldo kraken")
100
+ dkr[:sl].each { |k, v| puts(formata_saldos(k, v.to_d)) }
101
+
102
+ mostra_trades
103
+ mostra_ledger
104
+ return unless trades.count.positive?
105
+
106
+ puts("\nstring ajuste dias dos trades\n-h=#{kyt.map { |e| "#{e}:0" }.join(' ')}")
107
+ end
108
+
109
+ # @return [String] texto transacoes normais
110
+ def mostra_trades
111
+ return unless ops[:v] && trades.count.positive?
112
+
113
+ puts("\ntrade data hora tipo par ---preco ---------volume ---custo")
114
+ trades.each { |k, v| puts(formata_transacao_trades(k, v)) }
115
+ end
116
+
117
+ # @return [String] texto transacoes ledger
118
+ def mostra_ledger
119
+ return unless ops[:v] && ledger.count.positive?
120
+
121
+ puts("\nledger data hora tipo moeda -------quantidade -------------custo")
122
+ ledger.each { |k, v| puts(formata_transacao_ledger(k, v)) }
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Krkt
4
+ VERSION = '0.1.1'
5
+ end
metadata ADDED
@@ -0,0 +1,176 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: krkt
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Hernâni Rodrigues Vaz
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2020-09-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: curb
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: faraday
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: google-cloud-bigquery
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: json
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: thor
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: yard
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ description: Arquiva transactions kraken no bigquery. Pode ajustar dias para reposicionamento
126
+ temporal.
127
+ email:
128
+ - hernanirvaz@gmail.com
129
+ executables:
130
+ - krkt
131
+ extensions: []
132
+ extra_rdoc_files: []
133
+ files:
134
+ - ".gitignore"
135
+ - ".rubocop.yml"
136
+ - CODE_OF_CONDUCT.md
137
+ - Gemfile
138
+ - Gemfile.lock
139
+ - LICENSE.txt
140
+ - README.md
141
+ - Rakefile
142
+ - bin/console
143
+ - bin/setup
144
+ - exe/krkt
145
+ - krkt.gemspec
146
+ - lib/krkt.rb
147
+ - lib/krkt/bigquery.rb
148
+ - lib/krkt/client.rb
149
+ - lib/krkt/kraken.rb
150
+ - lib/krkt/version.rb
151
+ homepage: https://github.com/hernanirvaz/krkt
152
+ licenses:
153
+ - MIT
154
+ metadata:
155
+ yard.run: yard
156
+ homepage_uri: https://github.com/hernanirvaz/krkt
157
+ post_install_message:
158
+ rdoc_options: []
159
+ require_paths:
160
+ - lib
161
+ required_ruby_version: !ruby/object:Gem::Requirement
162
+ requirements:
163
+ - - ">="
164
+ - !ruby/object:Gem::Version
165
+ version: 2.3.0
166
+ required_rubygems_version: !ruby/object:Gem::Requirement
167
+ requirements:
168
+ - - ">="
169
+ - !ruby/object:Gem::Version
170
+ version: '0'
171
+ requirements: []
172
+ rubygems_version: 3.1.2
173
+ signing_key:
174
+ specification_version: 4
175
+ summary: Arquiva transactions kraken no bigquery.
176
+ test_files: []