straight-server 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +8 -0
  3. data/Gemfile +3 -1
  4. data/Gemfile.lock +57 -47
  5. data/Gemfile.travis +26 -0
  6. data/README.md +175 -22
  7. data/Rakefile +7 -0
  8. data/VERSION +1 -1
  9. data/benchmark/addons.yml +15 -0
  10. data/benchmark/config.yml +78 -0
  11. data/benchmark/default_last_keychain_id +1 -0
  12. data/benchmark/server_secret +1 -0
  13. data/bin/goliath.log +6 -0
  14. data/bin/goliath.log_stdout.log +51 -0
  15. data/bin/straight-server-benchmark +68 -0
  16. data/db/migrations/003_add_payment_id_to_orders.rb +13 -0
  17. data/db/migrations/004_add_description_to_orders.rb +11 -0
  18. data/db/migrations/005_add_orders_expiration_period_to_gateways.rb +11 -0
  19. data/db/migrations/006_add_check_order_status_in_db_first_to_gateways.rb +11 -0
  20. data/db/migrations/007_add_active_switcher_to_gateways.rb +11 -0
  21. data/db/migrations/008_add_order_counters_to_gateways.rb +11 -0
  22. data/db/migrations/009_add_hashed_id_to_gateways.rb +18 -0
  23. data/examples/client/client.dart +5 -0
  24. data/examples/client/client.html +7 -15
  25. data/examples/client/client.js +15 -0
  26. data/lib/straight-server/config.rb +1 -1
  27. data/lib/straight-server/gateway.rb +241 -59
  28. data/lib/straight-server/initializer.rb +170 -44
  29. data/lib/straight-server/logger.rb +1 -1
  30. data/lib/straight-server/order.rb +74 -9
  31. data/lib/straight-server/orders_controller.rb +23 -6
  32. data/lib/straight-server/random_string.rb +18 -0
  33. data/lib/straight-server/server.rb +44 -17
  34. data/lib/straight-server/utils/hash_string_to_sym_keys.rb +24 -0
  35. data/lib/straight-server.rb +6 -3
  36. data/spec/.straight/config.yml +16 -0
  37. data/spec/.straight/server_secret +1 -0
  38. data/spec/fixtures/addons.yml +19 -0
  39. data/spec/fixtures/test_addon.rb +8 -0
  40. data/spec/lib/gateway_spec.rb +93 -13
  41. data/spec/lib/initializer_spec.rb +104 -0
  42. data/spec/lib/order_spec.rb +59 -0
  43. data/spec/lib/orders_controller_spec.rb +34 -1
  44. data/spec/lib/utils/hash_string_to_sym_keys.rb +18 -0
  45. data/spec/spec_helper.rb +10 -2
  46. data/straight-server.gemspec +36 -8
  47. data/templates/addons.yml +15 -0
  48. data/templates/config.yml +41 -0
  49. metadata +47 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 34f009b0de8ffbad5c9cfb46cb3044cc69b61a65
4
- data.tar.gz: cf3543fde03d50bdf382957f347638ec83193497
3
+ metadata.gz: f8610bd49c87e428c82c658ecdc0a1f0e2299bfb
4
+ data.tar.gz: e046d7b179cafead65d803e4fb30e52d11a8bc11
5
5
  SHA512:
6
- metadata.gz: 5cc71b6d8ffd1fdd6b727db40a9a6c12687013119712b569c89ff39fdddf35f0420ed3617f0fc066de909f8bbb5fba77bba0040f4230dd6c7959f6488a8f4c4d
7
- data.tar.gz: 043c4bae520c57ac0b9e3fa96ec212ab58dbe4affe83f85a85c5f3798810681857ec8e48a78094904c6d2d9ffcd6fe6278ae6c60fc63846ab0a941668616aea6
6
+ metadata.gz: 0fda4cd1ecb67821380631da86fd6c2d4864c57ed5f0200b1b6d45508190a07b06e8c66e5e72a1b501df477b8da6c7f385ad4c7b059d50c51ce1f1176e570ef8
7
+ data.tar.gz: edb15d2d84f5de98901a3d0d3e18f7a2fb5279c6a9ed19418c9c8b400a9e6b006a3cf5b9d9d42cbcd82a7ae32861a32644048e2e0e851f32a0c09a5d71b79bae
data/.travis.yml ADDED
@@ -0,0 +1,8 @@
1
+ gemfile: Gemfile.travis
2
+ language: ruby
3
+ rvm:
4
+ - 2.1.0
5
+ services:
6
+ - redis-server
7
+ notifications:
8
+ slack: straight-payments:ovM1xPrG9BmKTHGkM0k42gkP
data/Gemfile CHANGED
@@ -5,8 +5,9 @@ gem "satoshi-unit"
5
5
  gem "goliath"
6
6
  gem "faye-websocket"
7
7
  gem "sequel"
8
- gem "logmaster", '0.1.2'
8
+ gem "logmaster", '0.1.5'
9
9
  gem "ruby-hmac"
10
+ gem "httparty"
10
11
 
11
12
  # Add dependencies to develop your gem here.
12
13
  # Include everything needed to run rake, tests, features, etc.
@@ -21,4 +22,5 @@ group :test do
21
22
  gem 'factory_girl'
22
23
  gem 'sqlite3'
23
24
  gem 'hashie'
25
+ gem 'redis'
24
26
  end
data/Gemfile.lock CHANGED
@@ -1,34 +1,34 @@
1
1
  GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
- activesupport (4.1.6)
5
- i18n (~> 0.6, >= 0.6.9)
4
+ activesupport (4.2.1)
5
+ i18n (~> 0.7)
6
6
  json (~> 1.7, >= 1.7.7)
7
7
  minitest (~> 5.1)
8
- thread_safe (~> 0.1)
8
+ thread_safe (~> 0.3, >= 0.3.4)
9
9
  tzinfo (~> 1.1)
10
- addressable (2.3.6)
10
+ addressable (2.3.8)
11
11
  async-rack (0.5.1)
12
12
  rack (~> 1.1)
13
13
  builder (3.2.2)
14
14
  descendants_tracker (0.0.4)
15
15
  thread_safe (~> 0.3, >= 0.3.1)
16
16
  diff-lcs (1.2.5)
17
- em-synchrony (1.0.3)
17
+ em-synchrony (1.0.4)
18
18
  eventmachine (>= 1.0.0.beta.1)
19
19
  em-websocket (0.3.8)
20
20
  addressable (>= 2.1.1)
21
21
  eventmachine (>= 0.12.9)
22
- eventmachine (1.0.3)
23
- factory_girl (4.4.0)
22
+ eventmachine (1.0.7)
23
+ factory_girl (4.5.0)
24
24
  activesupport (>= 3.0.0)
25
- faraday (0.9.0)
25
+ faraday (0.9.1)
26
26
  multipart-post (>= 1.2, < 3)
27
- faye-websocket (0.7.4)
27
+ faye-websocket (0.9.2)
28
28
  eventmachine (>= 0.12.0)
29
- websocket-driver (>= 0.3.1)
30
- ffi (1.9.3)
31
- git (1.2.8)
29
+ websocket-driver (>= 0.5.1)
30
+ ffi (1.9.8)
31
+ git (1.2.9.1)
32
32
  github_api (0.11.3)
33
33
  addressable (~> 2.3)
34
34
  descendants_tracker (~> 0.0.1)
@@ -48,10 +48,13 @@ GEM
48
48
  rack (>= 1.2.2)
49
49
  rack-contrib
50
50
  rack-respond_to
51
- hashie (3.3.1)
52
- highline (1.6.21)
51
+ hashie (3.4.1)
52
+ highline (1.7.2)
53
53
  http_parser.rb (0.6.0)
54
- i18n (0.6.11)
54
+ httparty (0.13.3)
55
+ json (~> 1.8)
56
+ multi_xml (>= 0.5.2)
57
+ i18n (0.7.0)
55
58
  jeweler (2.0.1)
56
59
  builder
57
60
  bundler (>= 1.0)
@@ -61,23 +64,23 @@ GEM
61
64
  nokogiri (>= 1.5.10)
62
65
  rake
63
66
  rdoc
64
- json (1.8.1)
65
- jwt (1.0.0)
67
+ json (1.8.2)
68
+ jwt (1.4.1)
66
69
  log4r (1.1.10)
67
- logmaster (0.1.2)
70
+ logmaster (0.1.5)
68
71
  pony
69
72
  mail (2.6.3)
70
73
  mime-types (>= 1.16, < 3)
71
- mime-types (2.4.3)
72
- mini_portile (0.6.0)
73
- minitest (5.4.1)
74
- money-tree (0.8.7)
74
+ mime-types (2.5)
75
+ mini_portile (0.6.2)
76
+ minitest (5.6.1)
77
+ money-tree (0.8.9)
75
78
  ffi
76
- multi_json (1.10.1)
79
+ multi_json (1.11.0)
77
80
  multi_xml (0.5.5)
78
81
  multipart-post (2.0.0)
79
- nokogiri (1.6.3.1)
80
- mini_portile (= 0.6.0)
82
+ nokogiri (1.6.6.2)
83
+ mini_portile (~> 0.6.0)
81
84
  oauth2 (1.0.0)
82
85
  faraday (>= 0.8, < 0.10)
83
86
  jwt (~> 1.0)
@@ -86,37 +89,42 @@ GEM
86
89
  rack (~> 1.2)
87
90
  pony (1.11)
88
91
  mail (>= 2.0)
89
- rack (1.5.2)
92
+ rack (1.6.0)
90
93
  rack-accept-media-types (0.9)
91
- rack-contrib (1.1.0)
94
+ rack-contrib (1.2.0)
92
95
  rack (>= 0.9.1)
93
96
  rack-respond_to (0.9.8)
94
97
  rack-accept-media-types (>= 0.6)
95
- rake (10.3.2)
96
- rdoc (4.1.2)
97
- json (~> 1.4)
98
- rspec (3.1.0)
99
- rspec-core (~> 3.1.0)
100
- rspec-expectations (~> 3.1.0)
101
- rspec-mocks (~> 3.1.0)
102
- rspec-core (3.1.2)
103
- rspec-support (~> 3.1.0)
104
- rspec-expectations (3.1.0)
98
+ rake (10.4.2)
99
+ rdoc (4.2.0)
100
+ redis (3.2.1)
101
+ rspec (3.2.0)
102
+ rspec-core (~> 3.2.0)
103
+ rspec-expectations (~> 3.2.0)
104
+ rspec-mocks (~> 3.2.0)
105
+ rspec-core (3.2.3)
106
+ rspec-support (~> 3.2.0)
107
+ rspec-expectations (3.2.1)
108
+ diff-lcs (>= 1.2.0, < 2.0)
109
+ rspec-support (~> 3.2.0)
110
+ rspec-mocks (3.2.1)
105
111
  diff-lcs (>= 1.2.0, < 2.0)
106
- rspec-support (~> 3.1.0)
107
- rspec-mocks (3.1.0)
108
- rspec-support (~> 3.1.0)
109
- rspec-support (3.1.0)
112
+ rspec-support (~> 3.2.0)
113
+ rspec-support (3.2.2)
110
114
  ruby-hmac (0.4.0)
111
- satoshi-unit (0.1.6)
112
- sequel (4.13.0)
113
- sqlite3 (1.3.9)
115
+ satoshi-unit (0.1.7)
116
+ sequel (4.22.0)
117
+ sqlite3 (1.3.10)
114
118
  straight (0.1.0)
119
+ httparty
115
120
  money-tree
116
- thread_safe (0.3.4)
121
+ satoshi-unit
122
+ thread_safe (0.3.5)
117
123
  tzinfo (1.2.2)
118
124
  thread_safe (~> 0.1)
119
- websocket-driver (0.3.4)
125
+ websocket-driver (0.5.4)
126
+ websocket-extensions (>= 0.1.0)
127
+ websocket-extensions (0.1.2)
120
128
 
121
129
  PLATFORMS
122
130
  ruby
@@ -128,8 +136,10 @@ DEPENDENCIES
128
136
  github_api (= 0.11.3)
129
137
  goliath
130
138
  hashie
139
+ httparty
131
140
  jeweler (~> 2.0.1)
132
- logmaster (= 0.1.2)
141
+ logmaster (= 0.1.5)
142
+ redis
133
143
  rspec
134
144
  ruby-hmac
135
145
  satoshi-unit
data/Gemfile.travis ADDED
@@ -0,0 +1,26 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem "straight", git: "https://github.com/snitko/straight.git"
4
+ gem "satoshi-unit"
5
+ gem "goliath"
6
+ gem "faye-websocket"
7
+ gem "sequel"
8
+ gem "logmaster", '0.1.5'
9
+ gem "ruby-hmac"
10
+ gem "httparty"
11
+
12
+ # Add dependencies to develop your gem here.
13
+ # Include everything needed to run rake, tests, features, etc.
14
+ group :development do
15
+ gem "bundler", "~> 1.0"
16
+ gem "jeweler", "~> 2.0.1"
17
+ gem "github_api", "0.11.3"
18
+ end
19
+
20
+ group :test do
21
+ gem 'rspec'
22
+ gem 'factory_girl'
23
+ gem 'sqlite3'
24
+ gem 'hashie'
25
+ gem 'redis'
26
+ end
data/README.md CHANGED
@@ -1,9 +1,16 @@
1
1
  Straight server
2
2
  ===============
3
- > A stand-alone Bitcoin payment gateway server
3
+ > A stand-alone Bitcoin payment gateway server.
4
4
  > Receives bitcoin payments directly into your wallet, holds no private keys
5
+ >
6
+ > It is used as a backend for the hosted service http://gear.mycelium.com
7
+ > Instead of installing the gateway yourself, you can just use
8
+ > Mycelium Gear and accept payments through it. Of course, straight
9
+ > into your wallet again - no private key required.
5
10
 
6
- > Website: http://straight.romansnitko.com
11
+ > Website: http://gear.mycelium.com
12
+
13
+ [![Build Status](https://travis-ci.org/snitko/straight-server.svg)](https://travis-ci.org/snitko/straight-server)
7
14
 
8
15
  If you'd like to accept Bitcoin payments on your website automatically, but you're not
9
16
  fond of services like Coinbase or Bitpay, which hold your bitcoins for you and require a ton
@@ -95,6 +102,22 @@ You can also subscribe to the order status changes using websockets at:
95
102
 
96
103
  It will send a message to the client upon the status change and close connection afterwards.
97
104
 
105
+ **Order expiration**
106
+ means that after a certain time has passed, it is no longer possible to pay for it. Each order holds
107
+ its creation time in `#created_at` field. In turn, each order's gateway has a field called
108
+ `#orders_expiration_period` (you can set it as an option in config file for each particular gateway or in the DB,
109
+ depending on what approach to storing gateways you use). After this time has passed, straight-server stops
110
+ checking whether new transactions appear on the order's bitcoin address and also changes order's status to 5 (expired).
111
+
112
+ Implications of restarting the server
113
+ -------------------------------------
114
+
115
+ If you shut the server down and then start it again, all unresolved orders (status < 2 and non-expired)
116
+ are automatically picked up and the server starts checking on them again until they expire. Please note
117
+ that you'd need to make sure your client side reconnects to the order's websocket again. This is because
118
+ on server shutdown, all websocket connections are closed, therefore, there's no way to automatically restore them.
119
+ It is thus client's responsibility to check when websocket is closed, then periodically try to connect to it again.
120
+
98
121
  Client Example
99
122
  --------------
100
123
  I've implemented a small client example app written purely in Dart. It creates new orders,
@@ -120,7 +143,8 @@ To create an order for the new gateway, simply send this request:
120
143
  Notice that the gateway id has changed to 2. Gateway ids are assigned according to the order in
121
144
  which they follow in the config file.
122
145
 
123
- ** Gateways from DB **
146
+ Gateways from DB
147
+ ----------------
124
148
  When you have too many gateways, it is unwise to keep them in the config file. In that case,
125
149
  you can store gateway settings in the DB. To do that, change `~/.straight/config.yml` setting
126
150
  'gateways_source: config` to `gateways_source: db`.
@@ -131,8 +155,8 @@ there is no standard way to manage gateways through a web interface. In the futu
131
155
  In general, it shouldn't be difficult, and may look like this:
132
156
 
133
157
  $ straight-console
134
-
135
- > g = Gateway.new
158
+
159
+ > gateway = Gateway.new
136
160
  > gateway.pubkey = 'xpub1234'
137
161
  > gateway.confirmations_required = 0
138
162
  > gateway.order_class = 'StraightServer::Order'
@@ -140,6 +164,25 @@ In general, it shouldn't be difficult, and may look like this:
140
164
  > gateway.save
141
165
  > exit
142
166
 
167
+ One important thing to remember when using DB based Gateways is that when you want to issue a request to
168
+ create a new order, you must use `Gateway#hashed_id` instead of `#id`. This is because otherwise it becomes very easy
169
+ for a third-party to just go through gateways consecutively.
170
+
171
+ For example, suppose you have a DB based gateway with id 23. The incorrect request to create a new order would be
172
+
173
+ POST /gateways/23/orders?amount=1 # THIS IS WRONG!
174
+
175
+ We first need to find that gateway's hashed id:
176
+
177
+ $ straight-console
178
+
179
+ > gateway = Gateway[23]
180
+ > gateway.hashed_id # => '587bb9b74e37f526eac47081ad61998726673760c77415d52a95bf38fba9cbe9'
181
+
182
+ And then we can make a correct request:
183
+
184
+ POST /gateways/587bb9b74e37f526eac47081ad61998726673760c77415d52a95bf38fba9cbe9/orders?amount=1
185
+
143
186
  Using signatures
144
187
  ----------------
145
188
  If you are running straight-server on a machine separate from your online stores, you
@@ -152,38 +195,32 @@ Go to your `~/.straight/config.yml` directory and set two options for each of yo
152
195
  check_signature: true
153
196
 
154
197
  This will force gateways to check signatures when you try to create a new order. A signature is
155
- a HMAC SHA1 hash of the secret and an order id. Because you need order id, it means you have
198
+ a HMAC SHA256 hash of the secret and an order id. Because you need order id, it means you have
156
199
  to actually provide it manually in the params. It can be any integer > 0, but it's better
157
200
  that it is a consecutive integer, so keep track of order ids in your application. Obviously,
158
201
  if an order with such an id already exists, the request will be rejected. A possible request
159
202
  (assuming secret is the line mentioned above in the sample config) would look like this:
160
203
 
161
- POST /gateways/1/orders?amount=1&order_id=1&signature=fb0e8d863621a3e6e2bf4e81f8ab70737190d92b
204
+ POST /gateways/1/orders?amount=1&order_id=1&signature=aa14c26b2ae892a8719b0c2c57f162b967bfbfbdcc38d8883714a0680cf20467
162
205
 
163
206
  An example of obtaining such signature in Ruby:
164
207
 
165
- require 'hmac'
166
- require 'hmac-sha1'
208
+ require 'openssl'
167
209
 
168
210
  secret = 'a long string of random chars'
169
- h = HMAC::SHA1.new(secret)
170
- h << '1' # order id
171
- h.hexdigest
211
+ OpenSSL::HMAC.digest('sha256', secret, "1").unpack("H*").first # "1" may be order_id here
172
212
 
173
213
  Straight server will also sign the callback url request. However, since the signature may be
174
214
  known to an attacker once it was used for creating a new order, we can no longer use it directly.
175
215
  Thus, Straight server will use a double signature calculated like this:
176
216
 
177
217
  secret = 'a long string of random chars'
178
- h = HMAC::SHA1.new(secret)
179
- h << '1' # order id
180
- h2 = HMAC::SHA1.new(secret)
181
- h2 << h.hexdigest
182
- h2.hexdigest
218
+ h1 = OpenSSL::HMAC.digest('sha256', secret, "1").unpack("H*").first
219
+ h2 = OpenSSL::HMAC.digest('sha256', secret, h1).unpack("H*").first
183
220
 
184
221
  and then send the request to the callback url with that signature:
185
222
 
186
- GET http://mystore.com/payment-callback?order_id=1&amount=1&status=2&address=1NZov2nm6gRCGW6r4q1qHtxXurrWNpPr1q&tid=tid1&data=some+random+data?signature=a61381c87ea3f7e6958ef779b6a9789ec966c2b9
223
+ GET http://mystore.com/payment-callback?order_id=1&amount=1&status=2&address=1NZov2nm6gRCGW6r4q1qHtxXurrWNpPr1q&tid=tid1&data=some+random+data?signature=aa14c26b2ae892a8719b0c2c57f162b967bfbfbdcc38d8883714a0680cf20467
187
224
 
188
225
  It is now up to your application to calculate that signature, compare it and
189
226
  make sure that only one such request is allowed (that is, if signature was used, it cannot be used again).
@@ -192,9 +229,40 @@ Querying the blockchain
192
229
  -----------------------
193
230
  Straight currently uses third-party services, such as Blokchain.info and Helloblock.io to track
194
231
  addresses and fetch transaction info. This means, you don't need to install bitcoind and store
195
- the whole blockchain on your server. If one service is down, it will automatically switch to another one. I will be adding more adapters in the future. It will also be possible to implement a cross check where if one service is lying about a transaction, I can check with another. In the future, I will add bitcoind support too for those who do not trust third-party services.
232
+ the whole blockchain on your server. If one service is down, it will automatically switch to another one.
233
+ I will be adding more adapters in the future. It will also be possible to implement a cross check where if
234
+ one service is lying about a transaction, I can check with another. In the future, I will add bitcoind support
235
+ too for those who do not trust third-party services.
236
+
237
+ To sum it up, there is nothing in the architecture of this software that says you should rely on third party services
238
+ to query the blockchain.
239
+
240
+ Counting orders
241
+ ---------------
242
+ For easy statistics and reports, it is desirable to know how many orders of each particular status each gateway has.
243
+ For that reason optional order counters are implemented. To enable order counters, you must first install manually *redis-server*
244
+ and then *redis* rubygem.
245
+
246
+ Then edit your config file and make sure the following options are set:
196
247
 
197
- To sum it up, there is nothing in the architecture of this software that says you should rely on third party services to query the blockchain.
248
+ environment: development # name your environment here
249
+ count_orders: true # enable order counting feature
250
+
251
+ redis:
252
+ host: localhost
253
+ port: 6379
254
+ db: null # change to 1, 2, 3 etc. or leave as is
255
+ password: null # if no password is needed, leave as is
256
+
257
+ After restarting the server, you can use `Gateway#order_counters` method which will
258
+ return a hash of all the counters. Here's an example output:
259
+
260
+ { new: 132, unconfirmed: 0, paid: 34, underpaid: 1, overpaid: 2, expired: 55 }
261
+
262
+ The default behaviour is to cache the output, so if you want fresh values, use `reload: true`
263
+ option on this method:
264
+
265
+ Gateway#order_counters(reload: true)
198
266
 
199
267
  Running in production
200
268
  ---------------------
@@ -212,6 +280,93 @@ turn on email notifications, so that when a FATAL errors occurs, an email is sen
212
280
 
213
281
  I would also recommend you to use something like *monit* daemon to monitor a *straight-server* process.
214
282
 
283
+ Running in different environments
284
+ ---------------------------------
285
+ Additionally, there is a `--config-dir` (short version is `-c`) option that allows you to set the
286
+ config directory for the server. It becomes quite convenient if you decide to run, for example, both
287
+ production and staging instances on one machine. I decided against having config file sections for each environment
288
+ as this would be more complicated and quite unnatural. Apart from different config files, one might argue you can have
289
+ a different set of addons and different versions of them in the `~/.straight/addons` dir. So it's better to keep them separate.
290
+
291
+ If you think of wrong examples out there, consider Rails: why would I want to have a database.yml file with both
292
+ development and production sections if I know for sure I'm only running this instance in production env?
293
+
294
+ So, with straight, you can simply create a separate config dir for each instance. For example, if I want to run
295
+ both production and staging on my server, I'd do this:
296
+
297
+ 1. Create `~/.straight/production` and `~/.straight/staging` dirs
298
+ 2. Run two instances like this:
299
+
300
+ straight-server --config-dir=~/.straight/production
301
+ straight-server --config-dir=~/.straight/staging
302
+
303
+ It's worth saying that currently, there is no default settings for production, staging or development.
304
+ It is you who defines what a production or a staging environment is, by changing the config file. Those words
305
+ are only used as examples. You may call your environment whatever you like.
306
+
307
+ However, environment name is currently used as a prefix for gateway order counters Redis entries
308
+ (see the respective README section). You can set the current environment name using a config file option, for example:
309
+
310
+ environment: development
311
+
312
+ Addons
313
+ ------
314
+ WARNING: this is currently work in progress. The final specification of how addons should be added
315
+ and how they interact with the server may change.
316
+
317
+ Currently there is only one use case for addons and thus only one way in which addons can interact with the server itself:
318
+ adding controllers and routes for them. Now let's look at how we should do that:
319
+
320
+ 1. All addons are placed under `~/.straight/addons/` (of course, it is wise to use symlinks).
321
+
322
+ 2. `./straight/addons.yml` file lists addons and tells straight-server what are the names of the files to be loaded.
323
+ The format of the file is the following:
324
+
325
+ my_addon # <- name doesn't affect anything, just shows up in the log file
326
+ path: addons/my_addon/lib/my_addon # <- This is unnecessary if addon is already in the LOAD_PATH
327
+ module: MyAddon # <- actual module should be a submodule of StraightServer::Addon
328
+
329
+ 3. In `./straight/addons/my_addon/lib/` we will place two files, `my_addon.rb` and 'my_controller.rb'. Below is their contents:
330
+
331
+
332
+ # my_addon.rb
333
+
334
+ require_relative 'my_controller'
335
+
336
+ module StraightServer
337
+ module Addon
338
+ module MyAddon
339
+
340
+ def self.extended(obj)
341
+ obj.add_route /\A\/my_controller/.*\Z/ do |env|
342
+ controller = MyController.new(env)
343
+ controller.show
344
+ end
345
+ end
346
+
347
+ end
348
+ end
349
+ end
350
+
351
+ As you can guess, `#add_route` is a straight-server's special method for defining routes, very similar to Rails.
352
+ The piece of code above will force all requests where urls are starting with `/my_controller` to be handled by
353
+ `MyController#show`:
354
+
355
+
356
+ # my_controller.rb
357
+
358
+ module StraightServer
359
+ class MyController
360
+ def show
361
+ [200, {}, "Hello world! This is MyController speaking!"]
362
+ end
363
+ end
364
+ end
365
+
366
+ And this in turn will render us the text "Hello world! This is MyController speaking!".
367
+ Here, we've just created our first addon.
368
+
369
+
215
370
  Requirements
216
371
  ------------
217
372
  Ruby 2.1 or later.
@@ -220,8 +375,6 @@ Donations
220
375
  ---------
221
376
  To go on with this project and make it truly awesome, I need more time. I can only buy free time with money, so any donation is highly appreciated. Please send bitcoins over to **1D3PknG4Lw1gFuJ9SYenA7pboF9gtXtdcD**
222
377
 
223
- There are [development plans](http://straight.romansnitko.com/#todo) for this software you might be interested in.
224
-
225
378
  Credits
226
379
  -------
227
380
  Author: [Roman Snitko](http://romansnitko.com)
data/Rakefile CHANGED
@@ -25,3 +25,10 @@ Jeweler::Tasks.new do |gem|
25
25
  end
26
26
  Jeweler::RubygemsDotOrgTasks.new
27
27
 
28
+ begin
29
+ require 'rspec/core/rake_task'
30
+ RSpec::Core::RakeTask.new(:spec)
31
+ task default: :spec
32
+ rescue LoadError
33
+ # no rspec available
34
+ end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.2
1
+ 0.2.0
@@ -0,0 +1,15 @@
1
+ # This is where you put info about your addons.
2
+ #
3
+ # Addons are just modules that extend the StraightServer::Server module.
4
+ #
5
+ # Addon modules can be both rubygems or files under ~/.straight/addons/.
6
+ # If ~/.straight/addons.yml contains a 'path' key for a particular addon, then it means
7
+ # the addon is placed under the ~/.straight/addons/. If not, it is assumed it is
8
+ # already in the LOAD_PATH somehow, with rubygems for example.
9
+ #
10
+ #
11
+ # Example:
12
+ #
13
+ # payment_ui: # <- name doesn't affect anything, just shows up in the log file
14
+ # path: addons/payment_ui # <- This is unnecessary if addon is already in the LOAD_PATH
15
+ # module: PaymentUI # <- actual module should be a submodule of StraightServer::Addon
@@ -0,0 +1,78 @@
1
+ # If set to db, then use DB table to store gateways,
2
+ # useful when your run many gateways on the same server.
3
+ gateways_source: config
4
+
5
+ environment: development
6
+
7
+ # This enabled order counting using Redis. Please see he README file for details.
8
+ # You're gonna need to install redis-server and redis rubygem on your system and provide
9
+ # redis-server connection details below.
10
+ count_orders: false
11
+
12
+ # Uncomment this if you want to use Gateway's order counters feature
13
+ # It requires redis.
14
+ #redis:
15
+ #host: localhost
16
+ #port: 6380
17
+ #db: null # change to 1, 2, 3 etc. or leave as is
18
+ #password: null # if no password is needed, leave as is
19
+
20
+ gateways:
21
+ default:
22
+ pubkey: xpub6AHA9hZDN11k2ijHMeS5QqHx2KP9aMBRhTDqANMnwVtdyw2TDYRmF8PjpvwUFcL1Et8Hj59S3gTSMcUQ5gAqTz3Wd8EsMTmF3DChhqPQBnU
23
+ confirmations_required: 0
24
+ order_class: "StraightServer::Order"
25
+ secret: 'secret'
26
+ check_signature: false
27
+ callback_url: 'http://localhost:3000/my_app/payment_callback'
28
+ default_currency: 'BTC'
29
+ orders_expiration_period: 600 # seconds
30
+
31
+ # This options decides whether we should also check the DB for status updates first
32
+ # when we check order status. That is, if we're tracking an order and this option
33
+ # is set to true, it first fetches the fields from the local DB, sees if the status has changed there,
34
+ # and if it did - we no longer need to query the blockchain.
35
+ #
36
+ # Usecase? Currently mostly debugging (so set it to false for production). For example,
37
+ # when testing payments, you don't actually want to pay, you can just run the server console,
38
+ # change order status in the DB and see how your client picks it up, showing you that your
39
+ # order has been paid for.
40
+ check_order_status_in_db_first: true # Consider changing to `false` in production.
41
+
42
+ # The order matters here, we check for prices with the first adapter,
43
+ # if it fails, move on to the next
44
+ exchange_rate_adapters:
45
+ - Bitpay
46
+ - Coinbase
47
+ - Bitstamp
48
+
49
+ # This affects whether it is possible to create a new order with the gateway.
50
+ # If it's set to false, then it won't be possible to create a new order, but
51
+ # it will keep checking on the existing ones.
52
+ active: true
53
+
54
+ logmaster:
55
+ log_level: INFO # Wise to change to WARN for production
56
+ file: straight.log
57
+ raise_exception: false
58
+ name: Straight server logger
59
+
60
+ # These options bellow send you email whenever a FATAL error occurs.
61
+ # You probably want to uncomment them for production. See https://github.com/snitko/logmaste
62
+ # for various email options.
63
+ #
64
+ #email_config:
65
+ #to: 'me@email.foo'
66
+ #from: "logmaster@yourapp.com"
67
+
68
+ db:
69
+ adapter: sqlite
70
+ name: straight.db # file is always located in ~/.straight
71
+
72
+ # No need to set these options for sqlite,
73
+ # but other DBs may require them.
74
+ #
75
+ #user: username
76
+ #password: password
77
+ #host: hostname
78
+ #port: 1234
@@ -0,0 +1 @@
1
+ 1520
@@ -0,0 +1 @@
1
+ fyjoq0s7c07l7iwk
data/bin/goliath.log ADDED
@@ -0,0 +1,6 @@
1
+ [10084:INFO] 2015-04-16 04:12:10 :: Starting server on 0.0.0.0:9696 in development mode. Watch out for stones.
2
+ [10084:INFO] 2015-04-16 04:12:21 :: Status: 200, Content-Length: 963, Response Time: 24.10ms
3
+ [10084:INFO] 2015-04-16 04:12:21 :: Status: 200, Content-Length: 366, Response Time: 3.11ms
4
+ [10084:INFO] 2015-04-16 04:12:26 :: Status: 200, Content-Length: 963, Response Time: 2.73ms
5
+ [10084:INFO] 2015-04-16 04:12:26 :: Status: 200, Content-Length: 366, Response Time: 3.25ms
6
+ [10084:INFO] 2015-04-16 04:12:40 :: Status: 500, Content-Length: 99, Response Time: 3.67ms