txcatcher 0.1.85 → 0.1.86

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
2
  SHA1:
3
- metadata.gz: b38221c572549590a66aeee17bd40d9faf33cd23
4
- data.tar.gz: 2f23c67720cc64544ed1feda49c656f5fca4e538
3
+ metadata.gz: 965c94026bab04e89b4371d58f6a4025ed22d2e1
4
+ data.tar.gz: d01ca825c2f1e0670a131c5d971d2452ce3b3f55
5
5
  SHA512:
6
- metadata.gz: c895162372eacf4102e6cf051e897a0af141fe4779e5865635121ebb57036954f6fd48f3e370cfa323a9795788cd0b5815ffec8a34a4c29962094bb82d924ead
7
- data.tar.gz: 73141d20ac2af88b1cbafbff568becbf8349ecb87df09ecebe58431ccb459c5325be8446076fd6277e5cee9a8eeb0c0911fd8a20cad06a36db1c98342cbd16ec
6
+ metadata.gz: dc4da965fd01031c17163e97518bfffcd1edb1be06a68a7e7b8cfa3c9f7e65d5394434c2d5cd346127a596e843487107d1076e5b443ea8d66dcf27f8108b9b18
7
+ data.tar.gz: c77d3e23861d9d619748842b10e3c809c8e4f8343051826f4803e54023cc09c8f152ebb191c476de509cd5c4276fe29e96b356f8fd92a0ae07b4863b4215b414
data/Gemfile CHANGED
@@ -5,6 +5,8 @@ gem "sequel"
5
5
  gem "ffi-rzmq"
6
6
  gem "crypto-unit"
7
7
  gem "sentry-raven"
8
+ gem "aws-sdk-ses"
9
+ gem "faraday"
8
10
 
9
11
  group :development do
10
12
  gem "bundler"
data/Gemfile.lock CHANGED
@@ -4,6 +4,15 @@ GEM
4
4
  addressable (2.4.0)
5
5
  async-rack (0.5.1)
6
6
  rack (~> 1.1)
7
+ aws-partitions (1.68.0)
8
+ aws-sdk-core (3.17.0)
9
+ aws-partitions (~> 1.0)
10
+ aws-sigv4 (~> 1.0)
11
+ jmespath (~> 1.0)
12
+ aws-sdk-ses (1.6.0)
13
+ aws-sdk-core (~> 3)
14
+ aws-sigv4 (~> 1.0)
15
+ aws-sigv4 (1.0.2)
7
16
  builder (3.2.3)
8
17
  crypto-unit (0.3.3)
9
18
  descendants_tracker (0.0.4)
@@ -57,6 +66,7 @@ GEM
57
66
  rake
58
67
  rdoc
59
68
  semver2
69
+ jmespath (1.3.1)
60
70
  jwt (1.5.6)
61
71
  log4r (1.1.10)
62
72
  mime-types (2.99.3)
@@ -105,8 +115,10 @@ PLATFORMS
105
115
  ruby
106
116
 
107
117
  DEPENDENCIES
118
+ aws-sdk-ses
108
119
  bundler
109
120
  crypto-unit
121
+ faraday
110
122
  ffi-rzmq
111
123
  goliath
112
124
  jeweler
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.85
1
+ 0.1.86
@@ -0,0 +1,148 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # This script is designed to be launched with cron every n minutes to knock on
4
+ # txcatcher's API and check whether new transactions are being picked up by it.
5
+ #
6
+ # New transactions are being fetched from a third-party source (currently: blockcypher.com)
7
+ # and config is read from the same config file as the one txcatcher uses.
8
+ #
9
+ # If an incosistency is found, reports are sent to email and to the logfile
10
+ # placed in your config_dir/txcatcher_monitor_errors.log
11
+ # Successful checks are logged into config_dir/txcatcher_monitor.log
12
+ #
13
+ # To run this script, specify config dir like this:
14
+ #
15
+ # txcatcher-monitor -c ~/.txcatcher/
16
+ #
17
+ # or
18
+ #
19
+ # txcatcher-monitor --config-dir ~/.txcatcher/
20
+ #
21
+ # When you generated an example config file with txcatcher on the first run,
22
+ # you should look at "monitor" section for settings related to this script.
23
+ #
24
+ # Just in case, here they are:
25
+ #
26
+ # monitor:
27
+ # txcatcher_url: "https://txcatcher-btc-mainnet.mydomain.com"
28
+ # blockchain_source_url: "https://api.blockcypher.com/v1/btc/main/txs"
29
+ # aws_ses:
30
+ # region: 'us-west-2'
31
+ # access_key: YOUR_AWS_KEY
32
+ # secret_access_key: YOUR_AWS_SECRET_ACCESS_KEY
33
+ # alert_mail:
34
+ # from: "alert@email.com"
35
+ # to:
36
+ # - "your@email.com"
37
+ # subject: "TxCatcher Alert"
38
+ #
39
+ # However remember, you'll also need a 'logger' section in this file.
40
+
41
+ require "rubygems"
42
+ require "faraday"
43
+ require "aws-sdk-ses"
44
+ require "yaml"
45
+ require 'time'
46
+ require_relative "../lib/txcatcher/config"
47
+ require_relative "../lib/txcatcher/logger"
48
+ require_relative "../lib/txcatcher/initializer"
49
+
50
+ def send_alert(subject, text)
51
+
52
+ return unless TxCatcher::Config["monitor"]["alert_mail"]
53
+
54
+ # Do not send emails more often than once in 1 hour
55
+ email_time_file = TxCatcher::Config.config_dir + "/txcatcher_monitor_last_email_time.txt"
56
+ t = Time.parse(File.read(email_time_file)) if File.exists?(email_time_file)
57
+ return if t && t > Time.now - 3600
58
+
59
+ ses_config = TxCatcher::Config["monitor"]["aws_ses"]
60
+ ses = Aws::SES::Client.new(
61
+ region: ses_config["region"],
62
+ access_key_id: ses_config["access_key"],
63
+ secret_access_key: ses_config["secret_access_key"]
64
+ )
65
+
66
+ resp = ses.send_email({
67
+ destination: { to_addresses: TxCatcher::Config["monitor"]["alert_mail"]["to"] },
68
+ source: TxCatcher::Config["monitor"]["alert_mail"]["from"],
69
+ message: {
70
+ body: { text: { charset: "utf-8", data: text }},
71
+ subject: { charset: "utf-8", data: subject }
72
+ }
73
+ })
74
+
75
+ File.open(email_time_file, 'w') { |f| f.write Time.now.to_s }
76
+
77
+ end
78
+
79
+ def latest_output_addr
80
+
81
+ response = Faraday.get do |req|
82
+ req.url TxCatcher::Config["monitor"]["blockchain_source_url"]
83
+ req.options.timeout = 5
84
+ req.options.open_timeout = 5
85
+ end
86
+ txs = JSON.parse(response.body)
87
+
88
+ txs.each do |tx|
89
+ if tx["outputs"] && tx["outputs"].first["addresses"]
90
+ tx["outputs"].first["addresses"].each do |addr|
91
+ # Blockcypher returns old Litecoin P2SH addresses which start with 3, which
92
+ # txcatcher doesn't support. Let's just ignore them.
93
+ if addr[0] != "3" || !TxCatcher::Config["monitor"]["ignore_3_litecoin_addr"]
94
+ return addr
95
+ end
96
+ end
97
+ end
98
+ end
99
+
100
+ end
101
+
102
+ def try_txcatcher(addr, sleep_time: 3)
103
+
104
+ raise StandardError
105
+
106
+ url = TxCatcher::Config["monitor"]["txcatcher_url"] + "/addr/#{addr}/utxo"
107
+
108
+ response = {}
109
+ 3.times do
110
+ sleep sleep_time # let's wait, perhaps txcatcher hasn't caught up
111
+ break unless (response = fetch_txcatcher_for_addr(addr)).empty?
112
+ end
113
+
114
+ if response.empty?
115
+ send_alert(
116
+ "TxCatcher response empty",
117
+ "TxCatcher returned an empty {} for #{url}"
118
+ )
119
+ TxCatcher::Logger.report("Checked #{url}, got empty response", :error)
120
+ else
121
+ TxCatcher::Logger.report("Checked #{url}, got #{response.size} utxos", :info)
122
+ end
123
+
124
+ end
125
+
126
+ def fetch_txcatcher_for_addr(addr)
127
+ response = Faraday.get do |req|
128
+ req.url TxCatcher::Config["monitor"]["txcatcher_url"] + "/addr/#{addr}1/utxo"
129
+ req.options.timeout = 5
130
+ req.options.open_timeout = 5
131
+ end
132
+ JSON.parse(response.body)
133
+ end
134
+
135
+ begin
136
+ include TxCatcher::Initializer
137
+ ConfigFile.set!
138
+ TxCatcher::Logger.set_log_file_names!(log: "txcatcher_monitor.log", error: "txcatcher_monitor_errors.log")
139
+ read_config_file
140
+ try_txcatcher(latest_output_addr)
141
+ rescue StandardError => e
142
+ TxCatcher::Logger.report(e, :error)
143
+ send_alert(
144
+ "TxCatcher monitor error",
145
+ "While checking #{TxCatcher::Config["monitor"]["txcatcher_url"]} response, got the following error\n\n" +
146
+ "#{e.to_s}\n\n#{e.backtrace.join("\n")}"
147
+ )
148
+ end
@@ -10,8 +10,16 @@ module TxCatcher
10
10
  unknown: 5
11
11
  }
12
12
 
13
+ @@log_file_name = "txcatcher.log"
14
+ @@error_log_file_name = "error.log"
15
+
13
16
  class << self
14
17
 
18
+ def set_log_file_names!(log: nil, error: nil)
19
+ @@log_file_name = log if log
20
+ @@error_log_file_name = error if error
21
+ end
22
+
15
23
  def report(message, log_level=:info, data: nil, timestamp: false)
16
24
  [:logfile, :stdout, :sentry].each do |out|
17
25
  if LOG_LEVELS[log_level] >= LOG_LEVELS[Config["logger"]["#{out}_level"].to_sym]
@@ -29,7 +37,7 @@ module TxCatcher
29
37
  end
30
38
 
31
39
  def report_to_logfile(message, log_level, data: nil, timestamp: true) # always gonna be forcing timestamp to be true here
32
- fn = LOG_LEVELS[log_level] >= LOG_LEVELS[:error] ? "error.log" : "txcatcher.log"
40
+ fn = LOG_LEVELS[log_level] >= LOG_LEVELS[:error] ? @@error_log_file_name : @@log_file_name
33
41
  fn = TxCatcher::Config.config_dir + "/#{fn}"
34
42
 
35
43
  File.open(fn, "a") do |f|
@@ -40,6 +48,7 @@ module TxCatcher
40
48
  end
41
49
 
42
50
  def report_to_sentry(e, log_level, data: nil, timestamp: timestamp)
51
+ return unless TxCatcher::Config["logger"]["sentry_dsn"]
43
52
  data ||= {}
44
53
  data.merge!(environment: Config["environment"], host: Config["host"], currency: Config["currency"])
45
54
  Raven.tags_context data
data/templates/config.yml CHANGED
@@ -24,6 +24,24 @@ logger:
24
24
  sentry_level: error
25
25
  sentry_dsn: null
26
26
 
27
+ monitor:
28
+ # REPLACE with your txcatcher url
29
+ txcatcher_url: "https://txcatcher-btc-mainnet.mydomain.com"
30
+
31
+ # LEAVE as is if on bitcoin mainnet, replace with
32
+ # https://api.blockcypher.com/v1/ltc/main/txs for Litecoin
33
+ # https://api.blockcypher.com/v1/btc/test3/txs for Bitcoin TESTNET
34
+ blockchain_source_url: "https://api.blockcypher.com/v1/btc/main/txs"
35
+ aws_ses:
36
+ region: 'us-west-2'
37
+ access_key: YOUR_AWS_KEY
38
+ secret_access_key: YOUR_AWS_SECRET_ACCESS_KEY
39
+ alert_mail:
40
+ from: "alert@email.com"
41
+ to:
42
+ - "your@email.com"
43
+ subject: "TxCatcher Alert"
44
+
27
45
  zeromq: bitcoind
28
46
  max_db_transactions_stored: 100000
29
47
  db_clean_period_seconds: 300
data/txcatcher.gemspec CHANGED
@@ -2,19 +2,19 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
- # stub: txcatcher 0.1.85 ruby lib
5
+ # stub: txcatcher 0.1.86 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "txcatcher"
9
- s.version = "0.1.85"
9
+ s.version = "0.1.86"
10
10
 
11
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
12
  s.require_paths = ["lib"]
13
13
  s.authors = ["Roman Snitko"]
14
- s.date = "2017-09-25"
15
- s.description = "Currently, the only job of this gem is to collect all new Bitcoin/Litecoin transactions, store them in a DB, index addresses."
14
+ s.date = "2018-03-05"
15
+ s.description = "Ccurrently, the only job of this gem is to collect all new Bitcoin/Litecoin transactions, store them in a DB, index addresses."
16
16
  s.email = "roman.snitko@gmail.com"
17
- s.executables = ["goliath.log", "goliath_stdout.log", "txcatcher"]
17
+ s.executables = ["txcatcher", "txcatcher-monitor"]
18
18
  s.extra_rdoc_files = [
19
19
  "LICENSE.txt",
20
20
  "README.md"
@@ -28,12 +28,13 @@ Gem::Specification.new do |s|
28
28
  "README.md",
29
29
  "Rakefile",
30
30
  "VERSION",
31
- "bin/goliath.log",
32
- "bin/goliath_stdout.log",
33
31
  "bin/txcatcher",
32
+ "bin/txcatcher-monitor",
34
33
  "db/migrations/001_create_transactions.rb",
35
34
  "db/migrations/002_create_addresses.rb",
36
35
  "db/migrations/003_create_deposits.rb",
36
+ "db/migrations/004_add_timestamps_to_transactions.rb",
37
+ "db/migrations/005_add_protected_flag_to_transactions.rb",
37
38
  "db/schema.rb",
38
39
  "lib/tasks/db.rake",
39
40
  "lib/txcatcher.rb",
@@ -42,20 +43,22 @@ Gem::Specification.new do |s|
42
43
  "lib/txcatcher/cleaner.rb",
43
44
  "lib/txcatcher/config.rb",
44
45
  "lib/txcatcher/initializer.rb",
46
+ "lib/txcatcher/logger.rb",
45
47
  "lib/txcatcher/models/address.rb",
46
48
  "lib/txcatcher/models/deposit.rb",
47
49
  "lib/txcatcher/models/transaction.rb",
48
50
  "lib/txcatcher/server.rb",
51
+ "lib/txcatcher/utils/crypto_unit.rb",
49
52
  "lib/txcatcher/utils/hash_string_to_sym_keys.rb",
50
53
  "spec/catcher_spec.rb",
51
54
  "spec/cleaner_spec.rb",
52
55
  "spec/config/config.yml.sample",
53
- "spec/config/txcatcher_test.db",
54
56
  "spec/fixtures/transaction.txt",
55
57
  "spec/fixtures/transaction_decoded_no_outputs.txt",
56
- "spec/models/address_spec.rb",
58
+ "spec/logger_spec.rb",
57
59
  "spec/models/transaction_spec.rb",
58
60
  "spec/spec_helper.rb",
61
+ "spec/utils/crypto_unit.rb",
59
62
  "templates/config.yml",
60
63
  "txcatcher.gemspec"
61
64
  ]
@@ -71,14 +74,20 @@ Gem::Specification.new do |s|
71
74
  s.add_runtime_dependency(%q<goliath>, [">= 0"])
72
75
  s.add_runtime_dependency(%q<sequel>, [">= 0"])
73
76
  s.add_runtime_dependency(%q<ffi-rzmq>, [">= 0"])
74
- s.add_runtime_dependency(%q<satoshi-unit>, [">= 0"])
77
+ s.add_runtime_dependency(%q<crypto-unit>, [">= 0"])
78
+ s.add_runtime_dependency(%q<sentry-raven>, [">= 0"])
79
+ s.add_runtime_dependency(%q<aws-sdk-ses>, [">= 0"])
80
+ s.add_runtime_dependency(%q<faraday>, [">= 0"])
75
81
  s.add_development_dependency(%q<bundler>, [">= 0"])
76
82
  s.add_development_dependency(%q<jeweler>, [">= 0"])
77
83
  else
78
84
  s.add_dependency(%q<goliath>, [">= 0"])
79
85
  s.add_dependency(%q<sequel>, [">= 0"])
80
86
  s.add_dependency(%q<ffi-rzmq>, [">= 0"])
81
- s.add_dependency(%q<satoshi-unit>, [">= 0"])
87
+ s.add_dependency(%q<crypto-unit>, [">= 0"])
88
+ s.add_dependency(%q<sentry-raven>, [">= 0"])
89
+ s.add_dependency(%q<aws-sdk-ses>, [">= 0"])
90
+ s.add_dependency(%q<faraday>, [">= 0"])
82
91
  s.add_dependency(%q<bundler>, [">= 0"])
83
92
  s.add_dependency(%q<jeweler>, [">= 0"])
84
93
  end
@@ -86,7 +95,10 @@ Gem::Specification.new do |s|
86
95
  s.add_dependency(%q<goliath>, [">= 0"])
87
96
  s.add_dependency(%q<sequel>, [">= 0"])
88
97
  s.add_dependency(%q<ffi-rzmq>, [">= 0"])
89
- s.add_dependency(%q<satoshi-unit>, [">= 0"])
98
+ s.add_dependency(%q<crypto-unit>, [">= 0"])
99
+ s.add_dependency(%q<sentry-raven>, [">= 0"])
100
+ s.add_dependency(%q<aws-sdk-ses>, [">= 0"])
101
+ s.add_dependency(%q<faraday>, [">= 0"])
90
102
  s.add_dependency(%q<bundler>, [">= 0"])
91
103
  s.add_dependency(%q<jeweler>, [">= 0"])
92
104
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: txcatcher
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.85
4
+ version: 0.1.86
5
5
  platform: ruby
6
6
  authors:
7
7
  - Roman Snitko
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-03-03 00:00:00.000000000 Z
11
+ date: 2018-03-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: goliath
@@ -80,6 +80,34 @@ dependencies:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: aws-sdk-ses
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: faraday
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'
83
111
  - !ruby/object:Gem::Dependency
84
112
  name: bundler
85
113
  requirement: !ruby/object:Gem::Requirement
@@ -112,9 +140,8 @@ description: Ccurrently, the only job of this gem is to collect all new Bitcoin/
112
140
  transactions, store them in a DB, index addresses.
113
141
  email: roman.snitko@gmail.com
114
142
  executables:
115
- - goliath.log
116
- - goliath_stdout.log
117
143
  - txcatcher
144
+ - txcatcher-monitor
118
145
  extensions: []
119
146
  extra_rdoc_files:
120
147
  - LICENSE.txt
@@ -128,9 +155,8 @@ files:
128
155
  - README.md
129
156
  - Rakefile
130
157
  - VERSION
131
- - bin/goliath.log
132
- - bin/goliath_stdout.log
133
158
  - bin/txcatcher
159
+ - bin/txcatcher-monitor
134
160
  - db/migrations/001_create_transactions.rb
135
161
  - db/migrations/002_create_addresses.rb
136
162
  - db/migrations/003_create_deposits.rb
data/bin/goliath.log DELETED
@@ -1,2 +0,0 @@
1
- [16007:INFO] 2017-09-23 23:23:59 :: Starting server on http://0.0.0.0:9498 in development mode. Watch out for stones.
2
- [16007:INFO] 2017-09-23 23:24:49 :: Stopping server...
File without changes