coinsync 0.2.0 → 0.2.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.
- checksums.yaml +4 -4
- data/lib/coinsync/config.rb +2 -7
- data/lib/coinsync/currency_conversion_task.rb +2 -2
- data/lib/coinsync/currency_converters/base.rb +8 -11
- data/lib/coinsync/currency_converters/exchangeratesapi.rb +14 -1
- data/lib/coinsync/currency_converters/nbp.rb +15 -1
- data/lib/coinsync/formatter.rb +2 -1
- data/lib/coinsync/importers/binance_api.rb +25 -16
- data/lib/coinsync/importers/bitbay20.rb +6 -3
- data/lib/coinsync/importers/bitbay_api.rb +17 -8
- data/lib/coinsync/importers/bitcurex.rb +4 -2
- data/lib/coinsync/importers/bitstamp_csv.rb +73 -0
- data/lib/coinsync/importers/bittrex_csv.rb +1 -1
- data/lib/coinsync/importers/default.rb +4 -1
- data/lib/coinsync/importers/kucoin_api.rb +11 -2
- data/lib/coinsync/outputs/list.rb +5 -1
- data/lib/coinsync/version.rb +1 -1
- metadata +24 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c0072156912886d0dda428c95b5421b230ce73bb
|
4
|
+
data.tar.gz: 3cb523a19af17908648fad02113d63fea9c7cb47
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 57fe540967120d3926ad5ac5e7883aae9f49147b6e6eba82e0f4b1c38aa1ea54af70adfd1140545e75fa1255907b9bd4a6860094dd75f9f77e96d78d227a52ce
|
7
|
+
data.tar.gz: 4aa898c645ca40f083720d22b517e7d3dc8c53ab8246bf977c5fbe00dccbc8188c7b44e34b220c119076b9597a373ba031e6c8bc5a047002c0923ea8b9f7d272
|
data/lib/coinsync/config.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'ostruct'
|
2
|
+
require 'tzinfo'
|
2
3
|
require 'yaml'
|
3
4
|
|
4
5
|
require_relative 'currencies'
|
@@ -28,8 +29,6 @@ module CoinSync
|
|
28
29
|
require(File.expand_path(File.join(*directory, file)))
|
29
30
|
end
|
30
31
|
end
|
31
|
-
|
32
|
-
set_timezone(timezone) if timezone
|
33
32
|
end
|
34
33
|
|
35
34
|
def sources
|
@@ -55,10 +54,6 @@ module CoinSync
|
|
55
54
|
Hash[included.map { |source| [source.key, source] }]
|
56
55
|
end
|
57
56
|
|
58
|
-
def set_timezone(timezone)
|
59
|
-
ENV['TZ'] = timezone
|
60
|
-
end
|
61
|
-
|
62
57
|
def base_cryptocurrencies
|
63
58
|
settings['base_cryptocurrencies'] || ['USDT', 'BTC', 'ETH', 'BNB', 'KCS', 'LTC', 'BCH', 'NEO']
|
64
59
|
end
|
@@ -88,7 +83,7 @@ module CoinSync
|
|
88
83
|
end
|
89
84
|
|
90
85
|
def timezone
|
91
|
-
settings['timezone']
|
86
|
+
settings['timezone'] && TZInfo::Timezone.get(settings['timezone'])
|
92
87
|
end
|
93
88
|
|
94
89
|
def translate(label)
|
@@ -26,7 +26,7 @@ module CoinSync
|
|
26
26
|
BigDecimal.new(1),
|
27
27
|
from: tx.bought_currency,
|
28
28
|
to: @target_currency,
|
29
|
-
|
29
|
+
time: tx.time
|
30
30
|
)
|
31
31
|
tx.converted.bought_amount = tx.bought_amount * tx.converted.exchange_rate
|
32
32
|
else
|
@@ -44,7 +44,7 @@ module CoinSync
|
|
44
44
|
BigDecimal.new(1),
|
45
45
|
from: tx.sold_currency,
|
46
46
|
to: @target_currency,
|
47
|
-
|
47
|
+
time: tx.time
|
48
48
|
)
|
49
49
|
tx.converted.sold_amount = tx.sold_amount * tx.converted.exchange_rate
|
50
50
|
else
|
@@ -23,20 +23,17 @@ module CoinSync
|
|
23
23
|
@cache = Cache.new(self.class.name.downcase.split('::').last)
|
24
24
|
end
|
25
25
|
|
26
|
-
def convert(amount, from:, to:,
|
26
|
+
def convert(amount, from:, to:, time:)
|
27
27
|
(amount > 0) or raise "#{self.class}: amount should be positive"
|
28
28
|
(amount.is_a?(BigDecimal)) or raise "#{self.class}: 'amount' should be a BigDecimal"
|
29
|
-
(from.is_a?(FiatCurrency)) or raise "#{self.class}: 'from' should be a FiatCurrency"
|
30
|
-
(to.is_a?(FiatCurrency)) or raise "#{self.class}: 'to' should be a FiatCurrency"
|
31
|
-
(date.is_a?(Date)) or raise "#{self.class}: 'date' should be a Date"
|
32
29
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
30
|
+
rate = get_conversion_rate(from: from, to: to, time: time)
|
31
|
+
|
32
|
+
rate * amount
|
33
|
+
end
|
34
|
+
|
35
|
+
def get_conversion_rate(from:, to:, time:)
|
36
|
+
raise "not implemented"
|
40
37
|
end
|
41
38
|
|
42
39
|
def finalize
|
@@ -10,12 +10,23 @@ module CoinSync
|
|
10
10
|
register_converter :exchangeratesapi
|
11
11
|
|
12
12
|
BASE_URL = "https://exchangeratesapi.io/api"
|
13
|
+
ECB_TIMEZONE = TZInfo::Timezone.get('Europe/Berlin')
|
13
14
|
|
14
15
|
class Exception < StandardError; end
|
15
16
|
class NoDataException < Exception; end
|
16
17
|
class BadRequestException < Exception; end
|
17
18
|
|
18
|
-
def
|
19
|
+
def get_conversion_rate(from:, to:, time:)
|
20
|
+
(from.is_a?(FiatCurrency)) or raise "#{self.class}: 'from' should be a FiatCurrency"
|
21
|
+
(to.is_a?(FiatCurrency)) or raise "#{self.class}: 'to' should be a FiatCurrency"
|
22
|
+
(time.is_a?(Time)) or raise "#{self.class}: 'time' should be a Time"
|
23
|
+
|
24
|
+
date = ECB_TIMEZONE.utc_to_local(time.utc).to_date
|
25
|
+
|
26
|
+
if rate = @cache[from, to, date]
|
27
|
+
return rate
|
28
|
+
end
|
29
|
+
|
19
30
|
response = Request.get("#{BASE_URL}/#{date}?base=#{from.code}")
|
20
31
|
|
21
32
|
case response
|
@@ -24,6 +35,8 @@ module CoinSync
|
|
24
35
|
rate = json['rates'][to.code.upcase]
|
25
36
|
raise NoDataException.new("No exchange rate found for #{to.code.upcase}") if rate.nil?
|
26
37
|
|
38
|
+
@cache[from, to, date] = rate
|
39
|
+
|
27
40
|
return rate
|
28
41
|
when Net::HTTPBadRequest
|
29
42
|
raise BadRequestException.new(response)
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'json'
|
2
2
|
require 'net/http'
|
3
|
+
require 'tzinfo'
|
3
4
|
|
4
5
|
require_relative 'base'
|
5
6
|
require_relative '../request'
|
@@ -10,14 +11,25 @@ module CoinSync
|
|
10
11
|
register_converter :nbp
|
11
12
|
|
12
13
|
BASE_URL = "https://api.nbp.pl/api"
|
14
|
+
POLISH_TIMEZONE = TZInfo::Timezone.get('Europe/Warsaw')
|
13
15
|
|
14
16
|
class Exception < StandardError; end
|
15
17
|
class NoDataException < Exception; end
|
16
18
|
class BadRequestException < Exception; end
|
17
19
|
|
18
|
-
def
|
20
|
+
def get_conversion_rate(from:, to:, time:)
|
21
|
+
(from.is_a?(FiatCurrency)) or raise "#{self.class}: 'from' should be a FiatCurrency"
|
22
|
+
(to.is_a?(FiatCurrency)) or raise "#{self.class}: 'to' should be a FiatCurrency"
|
23
|
+
(time.is_a?(Time)) or raise "#{self.class}: 'time' should be a Time"
|
24
|
+
|
19
25
|
raise "Only conversions to PLN are supported" if to.code != 'PLN'
|
20
26
|
|
27
|
+
date = POLISH_TIMEZONE.utc_to_local(time.utc).to_date
|
28
|
+
|
29
|
+
if rate = @cache[from, to, date]
|
30
|
+
return rate
|
31
|
+
end
|
32
|
+
|
21
33
|
response = Request.get("#{BASE_URL}/exchangerates/rates/a/#{from.code}/#{date - 8}/#{date - 1}/?format=json")
|
22
34
|
|
23
35
|
case response
|
@@ -26,6 +38,8 @@ module CoinSync
|
|
26
38
|
rate = json['rates'] && json['rates'].last && json['rates'].last['mid']
|
27
39
|
raise NoDataException.new("No exchange rate found for #{from.code.upcase}") if rate.nil?
|
28
40
|
|
41
|
+
@cache[from, to, date] = rate
|
42
|
+
|
29
43
|
return rate
|
30
44
|
when Net::HTTPBadRequest
|
31
45
|
raise BadRequestException.new(response)
|
data/lib/coinsync/formatter.rb
CHANGED
@@ -33,7 +33,8 @@ module CoinSync
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def format_time(time)
|
36
|
-
|
36
|
+
local_time = @config.timezone ? @config.timezone.utc_to_local(time.utc) : time
|
37
|
+
local_time.strftime(@config.time_format || '%Y-%m-%d %H:%M:%S')
|
37
38
|
end
|
38
39
|
|
39
40
|
def parse_decimal(string)
|
@@ -68,23 +68,30 @@ module CoinSync
|
|
68
68
|
transactions = []
|
69
69
|
|
70
70
|
@traded_pairs.uniq.each do |pair|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
71
|
+
lastId = 0
|
72
|
+
|
73
|
+
loop do
|
74
|
+
response = make_request('/v3/myTrades', limit: 500, fromId: lastId + 1, symbol: pair)
|
75
|
+
|
76
|
+
case response
|
77
|
+
when Net::HTTPSuccess
|
78
|
+
json = JSON.parse(response.body)
|
79
|
+
|
80
|
+
if !json.is_a?(Array)
|
81
|
+
raise "Binance importer: Invalid response: #{response.body}"
|
82
|
+
elsif json.empty?
|
83
|
+
break
|
84
|
+
else
|
85
|
+
json.each { |tx| tx['symbol'] = pair }
|
86
|
+
lastId = json.map { |j| j['id'] }.sort.last
|
87
|
+
|
88
|
+
transactions.concat(json)
|
89
|
+
end
|
90
|
+
when Net::HTTPBadRequest
|
91
|
+
raise "Binance importer: Bad request: #{response} (#{response.body})"
|
92
|
+
else
|
93
|
+
raise "Binance importer: Bad response: #{response}"
|
79
94
|
end
|
80
|
-
|
81
|
-
json.each { |tx| tx['symbol'] = pair }
|
82
|
-
|
83
|
-
transactions.concat(json)
|
84
|
-
when Net::HTTPBadRequest
|
85
|
-
raise "Binance importer: Bad request: #{response} (#{response.body})"
|
86
|
-
else
|
87
|
-
raise "Binance importer: Bad response: #{response}"
|
88
95
|
end
|
89
96
|
end
|
90
97
|
|
@@ -187,6 +194,8 @@ module CoinSync
|
|
187
194
|
private
|
188
195
|
|
189
196
|
def make_request(path, params = {}, signed = true)
|
197
|
+
print '.'
|
198
|
+
|
190
199
|
if signed
|
191
200
|
(@api_key && @secret_key) or raise "Public and secret API keys must be provided"
|
192
201
|
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'bigdecimal'
|
2
2
|
require 'csv'
|
3
3
|
require 'time'
|
4
|
+
require 'tzinfo'
|
4
5
|
|
5
6
|
require_relative 'base'
|
6
7
|
require_relative '../currencies'
|
@@ -24,10 +25,12 @@ module CoinSync
|
|
24
25
|
class HistoryEntry
|
25
26
|
attr_accessor :date, :accounting_date, :type, :amount, :currency
|
26
27
|
|
28
|
+
POLISH_TIMEZONE = TZInfo::Timezone.get('Europe/Warsaw')
|
29
|
+
|
27
30
|
def initialize(line)
|
28
|
-
|
29
|
-
@
|
30
|
-
|
31
|
+
@date = POLISH_TIMEZONE.local_to_utc(Time.parse(line[0])) unless line[0] == '-'
|
32
|
+
@accounting_date = POLISH_TIMEZONE.local_to_utc(Time.parse(line[1])) unless line[1] == '-'
|
33
|
+
|
31
34
|
@type = line[2]
|
32
35
|
|
33
36
|
amount, currency = line[3].split(' ')
|
@@ -3,6 +3,7 @@ require 'json'
|
|
3
3
|
require 'net/http'
|
4
4
|
require 'openssl'
|
5
5
|
require 'time'
|
6
|
+
require 'tzinfo'
|
6
7
|
require 'uri'
|
7
8
|
|
8
9
|
require_relative 'base'
|
@@ -22,14 +23,16 @@ module CoinSync
|
|
22
23
|
OP_SALE = '-pay_for_currency'
|
23
24
|
OP_FEE = '-fee'
|
24
25
|
|
25
|
-
MAX_TIME_DIFFERENCE =
|
26
|
+
MAX_TIME_DIFFERENCE = 5.0
|
26
27
|
TRANSACTION_TYPES = [OP_PURCHASE, OP_SALE, OP_FEE]
|
27
28
|
|
29
|
+
POLISH_TIMEZONE = TZInfo::Timezone.get('Europe/Warsaw')
|
30
|
+
|
28
31
|
class HistoryEntry
|
29
32
|
attr_accessor :date, :amount, :type, :currency
|
30
33
|
|
31
34
|
def initialize(hash)
|
32
|
-
@date = Time.parse(hash['time'])
|
35
|
+
@date = POLISH_TIMEZONE.local_to_utc(Time.parse(hash['time']))
|
33
36
|
@amount = BigDecimal.new(hash['amount'])
|
34
37
|
@type = hash['operation_type']
|
35
38
|
@currency = parse_currency(hash['currency'])
|
@@ -94,7 +97,8 @@ module CoinSync
|
|
94
97
|
currencies.each do |currency|
|
95
98
|
sleep 1 # rate limiting
|
96
99
|
|
97
|
-
|
100
|
+
# TODO: does this limit really work? (no way to test it really and docs don't mention a max value)
|
101
|
+
response = make_request('history', currency: currency, limit: 10000)
|
98
102
|
|
99
103
|
case response
|
100
104
|
when Net::HTTPSuccess
|
@@ -144,15 +148,17 @@ module CoinSync
|
|
144
148
|
|
145
149
|
next unless TRANSACTION_TYPES.include?(entry.type)
|
146
150
|
|
147
|
-
if !matching.empty?
|
148
|
-
|
151
|
+
if !matching.empty?
|
152
|
+
must_match = matching.any? { |e| (e.date - entry.date).abs > MAX_TIME_DIFFERENCE }
|
153
|
+
transaction = process_matched(matching, must_match)
|
154
|
+
transactions << transaction if transaction
|
149
155
|
end
|
150
156
|
|
151
157
|
matching << entry
|
152
158
|
end
|
153
159
|
|
154
160
|
if !matching.empty?
|
155
|
-
transactions << process_matched(matching)
|
161
|
+
transactions << process_matched(matching, true)
|
156
162
|
end
|
157
163
|
|
158
164
|
transactions
|
@@ -161,7 +167,7 @@ module CoinSync
|
|
161
167
|
|
162
168
|
private
|
163
169
|
|
164
|
-
def process_matched(matching)
|
170
|
+
def process_matched(matching, must_match)
|
165
171
|
if matching.length % 3 == 0
|
166
172
|
purchases = matching.select { |tx| tx.type == OP_PURCHASE }
|
167
173
|
sales = matching.select { |tx| tx.type == OP_SALE }
|
@@ -186,7 +192,10 @@ module CoinSync
|
|
186
192
|
end
|
187
193
|
end
|
188
194
|
|
189
|
-
|
195
|
+
if must_match
|
196
|
+
raise "BitBay API importer error: Couldn't match some history lines: " +
|
197
|
+
matching.map { |m| "\n#{m.inspect}" }.join
|
198
|
+
end
|
190
199
|
end
|
191
200
|
|
192
201
|
def make_request(method, params = {})
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'bigdecimal'
|
2
2
|
require 'csv'
|
3
3
|
require 'time'
|
4
|
+
require 'tzinfo'
|
4
5
|
|
5
6
|
require_relative 'base'
|
6
7
|
require_relative '../currencies'
|
@@ -14,11 +15,12 @@ module CoinSync
|
|
14
15
|
class HistoryEntry
|
15
16
|
attr_accessor :lp, :type, :date, :market, :amount, :price, :total, :fee, :fee_currency, :id
|
16
17
|
|
18
|
+
POLISH_TIMEZONE = TZInfo::Timezone.get('Europe/Warsaw')
|
19
|
+
|
17
20
|
def initialize(line)
|
18
|
-
# TODO: force parsing in Polish timezone
|
19
21
|
@lp = line[0].to_i
|
20
22
|
@type = line[1]
|
21
|
-
@date = Time.parse(line[2])
|
23
|
+
@date = POLISH_TIMEZONE.local_to_utc(Time.parse(line[2]))
|
22
24
|
@market = FiatCurrency.new(line[3])
|
23
25
|
@amount = BigDecimal.new(line[4])
|
24
26
|
@price = BigDecimal.new(line[5].split(' ').first)
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'bigdecimal'
|
2
|
+
require 'csv'
|
3
|
+
require 'time'
|
4
|
+
|
5
|
+
require_relative 'base'
|
6
|
+
require_relative '../currencies'
|
7
|
+
require_relative '../transaction'
|
8
|
+
|
9
|
+
module CoinSync
|
10
|
+
module Importers
|
11
|
+
class BitstampCSV < Base
|
12
|
+
register_importer :bitstamp_csv
|
13
|
+
|
14
|
+
class HistoryEntry
|
15
|
+
attr_accessor :lp, :type, :date, :market, :amount, :price, :total, :fee, :fee_currency, :id
|
16
|
+
|
17
|
+
def initialize(line)
|
18
|
+
@type = line[0]
|
19
|
+
@date = Time.parse(line[1])
|
20
|
+
@account = line[2]
|
21
|
+
|
22
|
+
|
23
|
+
@lp = line[0].to_i
|
24
|
+
@market = FiatCurrency.new(line[3])
|
25
|
+
@amount = BigDecimal.new(line[4])
|
26
|
+
@price = BigDecimal.new(line[5].split(' ').first)
|
27
|
+
@total = BigDecimal.new(line[6].split(' ').first)
|
28
|
+
@fee = BigDecimal.new(line[7].split(' ').first)
|
29
|
+
@fee_currency = line[7].split(' ').last
|
30
|
+
@id = line[8].to_i
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def read_transaction_list(source)
|
35
|
+
csv = CSV.new(source, col_sep: ',')
|
36
|
+
|
37
|
+
transactions = []
|
38
|
+
bitcoin = CryptoCurrency.new('BTC')
|
39
|
+
|
40
|
+
csv.each do |line|
|
41
|
+
next if line.empty?
|
42
|
+
next if line[0] == 'Type'
|
43
|
+
|
44
|
+
entry = HistoryEntry.new(line)
|
45
|
+
|
46
|
+
if entry.type == 'Kup'
|
47
|
+
transactions << Transaction.new(
|
48
|
+
exchange: 'Bitcurex',
|
49
|
+
bought_currency: bitcoin,
|
50
|
+
sold_currency: entry.market,
|
51
|
+
time: entry.date,
|
52
|
+
bought_amount: entry.amount,
|
53
|
+
sold_amount: entry.total
|
54
|
+
)
|
55
|
+
elsif entry.type == 'Sprzedaj'
|
56
|
+
transactions << Transaction.new(
|
57
|
+
exchange: 'Bitcurex',
|
58
|
+
bought_currency: entry.market,
|
59
|
+
sold_currency: bitcoin,
|
60
|
+
time: entry.date,
|
61
|
+
bought_amount: entry.total,
|
62
|
+
sold_amount: entry.amount
|
63
|
+
)
|
64
|
+
else
|
65
|
+
raise "Bitcurex importer error: unexpected entry type '#{entry.type}'"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
transactions.reverse
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -58,7 +58,7 @@ module CoinSync
|
|
58
58
|
transactions << Transaction.new(
|
59
59
|
exchange: 'Bittrex',
|
60
60
|
time: entry.time_closed,
|
61
|
-
bought_amount: entry.price - entry.commission,
|
61
|
+
bought_amount: entry.price - entry.commission,
|
62
62
|
bought_currency: entry.currency,
|
63
63
|
sold_amount: entry.quantity,
|
64
64
|
sold_currency: entry.asset
|
@@ -68,7 +68,10 @@ module CoinSync
|
|
68
68
|
entry.lp = line[0].to_i
|
69
69
|
entry.exchange = line[1]
|
70
70
|
entry.type = line[2]
|
71
|
-
|
71
|
+
|
72
|
+
time = Time.parse(line[3])
|
73
|
+
entry.date = @config.timezone ? @config.timezone.local_to_utc(time) : time
|
74
|
+
|
72
75
|
entry.amount = @formatter.parse_decimal(line[4])
|
73
76
|
entry.asset = CryptoCurrency.new(line[5])
|
74
77
|
entry.total = @formatter.parse_decimal(line[6])
|
@@ -43,7 +43,8 @@ module CoinSync
|
|
43
43
|
end
|
44
44
|
|
45
45
|
def import_transactions(filename)
|
46
|
-
|
46
|
+
# TODO: what if there's more than 100? (looks like we might need to switch to loading each market separately…)
|
47
|
+
response = make_request('/order/dealt', limit: 100)
|
47
48
|
|
48
49
|
case response
|
49
50
|
when Net::HTTPSuccess
|
@@ -128,8 +129,16 @@ module CoinSync
|
|
128
129
|
sold_amount: entry.deal_value,
|
129
130
|
sold_currency: entry.coin_type_pair
|
130
131
|
)
|
132
|
+
elsif entry.direction == 'SELL'
|
133
|
+
transactions << Transaction.new(
|
134
|
+
exchange: 'Kucoin',
|
135
|
+
time: entry.created_at,
|
136
|
+
sold_amount: entry.amount,
|
137
|
+
sold_currency: entry.coin_type,
|
138
|
+
bought_amount: entry.deal_value - entry.fee,
|
139
|
+
bought_currency: entry.coin_type_pair
|
140
|
+
)
|
131
141
|
else
|
132
|
-
# TODO sell
|
133
142
|
raise "Kucoin importer error: unexpected entry direction '#{entry.direction}'"
|
134
143
|
end
|
135
144
|
end
|
@@ -16,7 +16,7 @@ module CoinSync
|
|
16
16
|
csv << headers
|
17
17
|
|
18
18
|
transactions.each do |tx|
|
19
|
-
|
19
|
+
process_transaction(tx, csv)
|
20
20
|
end
|
21
21
|
end
|
22
22
|
end
|
@@ -45,6 +45,10 @@ module CoinSync
|
|
45
45
|
line
|
46
46
|
end
|
47
47
|
|
48
|
+
def process_transaction(tx, csv)
|
49
|
+
csv << transaction_to_csv(tx)
|
50
|
+
end
|
51
|
+
|
48
52
|
def transaction_to_csv(tx)
|
49
53
|
if tx.purchase? || tx.sale?
|
50
54
|
fiat_transaction_to_csv(tx)
|
data/lib/coinsync/version.rb
CHANGED
metadata
CHANGED
@@ -1,15 +1,35 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: coinsync
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kuba Suder
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-04-
|
12
|
-
dependencies:
|
11
|
+
date: 2018-04-26 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: tzinfo
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.2.5
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '2.0'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 1.2.5
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '2.0'
|
13
33
|
description:
|
14
34
|
email:
|
15
35
|
- jakub.suder@gmail.com
|
@@ -45,6 +65,7 @@ files:
|
|
45
65
|
- lib/coinsync/importers/bitbay20.rb
|
46
66
|
- lib/coinsync/importers/bitbay_api.rb
|
47
67
|
- lib/coinsync/importers/bitcurex.rb
|
68
|
+
- lib/coinsync/importers/bitstamp_csv.rb
|
48
69
|
- lib/coinsync/importers/bittrex_api.rb
|
49
70
|
- lib/coinsync/importers/bittrex_csv.rb
|
50
71
|
- lib/coinsync/importers/changelly.rb
|