txcatcher 0.1.85 → 0.1.86
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/Gemfile +2 -0
- data/Gemfile.lock +12 -0
- data/VERSION +1 -1
- data/bin/txcatcher-monitor +148 -0
- data/lib/txcatcher/logger.rb +10 -1
- data/templates/config.yml +18 -0
- data/txcatcher.gemspec +24 -12
- metadata +32 -6
- data/bin/goliath.log +0 -2
- data/bin/goliath_stdout.log +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 965c94026bab04e89b4371d58f6a4025ed22d2e1
|
4
|
+
data.tar.gz: d01ca825c2f1e0670a131c5d971d2452ce3b3f55
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dc4da965fd01031c17163e97518bfffcd1edb1be06a68a7e7b8cfa3c9f7e65d5394434c2d5cd346127a596e843487107d1076e5b443ea8d66dcf27f8108b9b18
|
7
|
+
data.tar.gz: c77d3e23861d9d619748842b10e3c809c8e4f8343051826f4803e54023cc09c8f152ebb191c476de509cd5c4276fe29e96b356f8fd92a0ae07b4863b4215b414
|
data/Gemfile
CHANGED
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.
|
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
|
data/lib/txcatcher/logger.rb
CHANGED
@@ -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] ?
|
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.
|
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.
|
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 = "
|
15
|
-
s.description = "
|
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 = ["
|
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/
|
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<
|
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<
|
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<
|
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.
|
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-
|
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
data/bin/goliath_stdout.log
DELETED
File without changes
|