coinbase 0.0.1 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of coinbase might be problematic. Click here for more details.

data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ test/tmp
15
+ test/version_tmp
16
+ tmp
17
+ .tddium*
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ rvm:
2
+ - 1.9.2
3
+ - 1.9.3
4
+ - jruby-19mode
5
+ - rbx-19mode
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in coinbase-ruby.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Coinbase
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,277 @@
1
+ **ALERT! October 18th, 2013** If you are getting SSL certificate validation errors very sorry for the trouble here.
2
+ We needed to update our certificate which was about to expire, and unfortunately broke the certificate validation that was embedded in the gem.
3
+ To resolve this you will need to update to version `1.2.4`:
4
+
5
+ To update:
6
+
7
+ gem install coinbase
8
+ bundle update coinbase
9
+
10
+ And ensure you are on version `1.2.4`. Apologies again for the trouble!
11
+
12
+
13
+ # Coinbase
14
+
15
+ An easy way to buy, send, and accept [bitcoin](http://en.wikipedia.org/wiki/Bitcoin) through the [Coinbase API](https://coinbase.com/docs/api/overview).
16
+
17
+ This gem uses the [api key authentication method](https://coinbase.com/docs/api/authentication) which is an easy way to get started if you only need to connect to your own Coinbase account. If you need other users to grant your application access, you may want to try an OAuth2 integration instead using the [OAuth2 Ruby Gem](https://github.com/intridea/oauth2) as a starting point.
18
+
19
+ ## Installation
20
+
21
+ Add this line to your application's Gemfile:
22
+
23
+ gem 'coinbase'
24
+
25
+ Then execute:
26
+
27
+ $ bundle
28
+
29
+ Or install it yourself as:
30
+
31
+ $ gem install coinbase
32
+
33
+ ## Usage
34
+
35
+ Start by [enabling an API Key on your account](https://coinbase.com/account/integrations).
36
+
37
+ Next, create an instance of the client and pass it your API Key + Secret as parameters.
38
+
39
+ ```ruby
40
+ coinbase = Coinbase::Client.new(ENV['COINBASE_API_KEY'], ENV['COINBASE_API_SECRET'])
41
+ ```
42
+
43
+ Notice here that we did not hard code the API key into our codebase, but set it in an environment variable instead. This is just one example, but keeping your credentials separate from your code base is a good [security practice](https://coinbase.com/docs/api/authentication#security).
44
+
45
+ Now you can call methods on `coinbase` similar to the ones described in the [api reference](https://coinbase.com/api/doc). For example:
46
+
47
+ ```ruby
48
+ coinbase.balance
49
+ => #<Money fractional:20035300000 currency:BTC>
50
+ coinbase.balance.format
51
+ => "200.35300000 BTC"
52
+ coinbase.balance.to_f
53
+ => 200.353
54
+ ```
55
+
56
+ [Money objects](https://github.com/RubyMoney/money) are returned for most amounts dealing with currency. You can call `to_f`, `format`, or perform math operations on money objects.
57
+
58
+ ## Examples
59
+
60
+ ### Check your balance
61
+
62
+ ```ruby
63
+ coinbase.balance.to_f
64
+ => 200.353 # BTC amount
65
+ ```
66
+
67
+ ### Send bitcoin
68
+
69
+ ```ruby
70
+ r = coinbase.send_money 'user@example.com', 1.23
71
+ r.success?
72
+ => true
73
+ r.transaction.status
74
+ => 'pending' # this will change to 'complete' in a few seconds if you are sending coinbase-to-coinbase, otherwise it will take about 1 hour, 'complete' means it cannot be reversed or canceled
75
+ r.transaction.id
76
+ => '501a1791f8182b2071000087'
77
+ r.transaction.recipient.email
78
+ => 'user@example.com'
79
+ r.to_hash
80
+ => ... # raw hash response
81
+ ```
82
+
83
+ You can also send money in [a number of currencies](https://github.com/coinbase/coinbase-ruby/blob/master/supported_currencies.json). The amount will be automatically converted to the correct BTC amount using the current exchange rate.
84
+
85
+ ```ruby
86
+ r = coinbase.send_money 'user@example.com', 1.23.to_money('AUS')
87
+ r.transaction.amount.format
88
+ => "0.06713955 BTC"
89
+ ```
90
+
91
+ The first parameter can also be a bitcoin address and the third parameter can be a note or description of the transaction. Descriptions are only visible on Coinbase (not on the general bitcoin network).
92
+
93
+ ```ruby
94
+ r = coinbase.send_money 'mpJKwdmJKYjiyfNo26eRp4j6qGwuUUnw9x', 2.23.to_money("USD"), "thanks for the coffee!"
95
+ r.transaction.recipient_address
96
+ => "mpJKwdmJKYjiyfNo26eRp4j6qGwuUUnw9x"
97
+ r.transaction.notes
98
+ => "thanks for the coffee!"
99
+ ```
100
+
101
+ ### Request bitcoin
102
+
103
+ This will send an email to the recipient, requesting payment, and give them an easy way to pay.
104
+
105
+ ```ruby
106
+ r = coinbase.request_money 'client@example.com', 50, "contractor hours in January (website redesign for 50 BTC)"
107
+ r.transaction.request?
108
+ => true
109
+ r.transaction.id
110
+ => '501a3554f8182b2754000003'
111
+ r = coinbase.resend_request '501a3554f8182b2754000003'
112
+ r.success?
113
+ => true
114
+ r = coinbase.cancel_request '501a3554f8182b2754000003'
115
+ r.success?
116
+ => true
117
+ # from the other account
118
+ r = coinbase.complete_request '501a3554f8182b2754000003'
119
+ r.success?
120
+ => true
121
+ ```
122
+
123
+ ### List your current transactions
124
+
125
+ Sorted in descending order by timestamp, 30 per page. You can pass an integer as the first param to page through results, for example `coinbase.transactions(2)`.
126
+
127
+ ```ruby
128
+ r = coinbase.transactions
129
+ r.current_page
130
+ => 1
131
+ r.num_pages
132
+ => 7
133
+ r.transactions.collect{|t| t.transaction.id }
134
+ => ["5018f833f8182b129c00002f", "5018f833f8182b129c00002e", ...]
135
+ r.transactions.collect{|t| t.transaction.amount.format }
136
+ => ["-1.10000000 BTC", "42.73120000 BTC", ...]
137
+ ```
138
+
139
+ Transactions will always have an `id` attribute which is the primary way to identity them through the Coinbase api. They will also have a `hsh` (bitcoin hash) attribute once they've been broadcast to the network (usually within a few seconds).
140
+
141
+ ### Check bitcoin prices
142
+
143
+ Check the buy or sell price by passing a `quantity` of bitcoin that you'd like to buy or sell. This price includes Coinbase's fee of 1% and the bank transfer fee of $0.15.
144
+
145
+ ```ruby
146
+ coinbase.buy_price(1).format
147
+ => "$17.95"
148
+ coinbase.buy_price(30).format
149
+ => "$539.70"
150
+ ```
151
+
152
+
153
+ ```ruby
154
+ coinbase.sell_price(1).format
155
+ => "$17.93"
156
+ coinbase.buy_price(30).format
157
+ => "$534.60"
158
+ ```
159
+
160
+ ### Buy or Sell bitcoin
161
+
162
+ Buying and selling bitcoin requires you to [add a payment method](https://coinbase.com/buys) through the web app first.
163
+
164
+ Then you can call `buy!` or `sell!` and pass a `quantity` of bitcoin you want to buy (as a float or integer).
165
+
166
+ ```ruby
167
+ r = coinbase.buy!(1)
168
+ r.transfer.code
169
+ => '6H7GYLXZ'
170
+ r.transfer.btc.format
171
+ => "1.00000000 BTC"
172
+ r.transfer.total.format
173
+ => "$17.95"
174
+ r.transfer.payout_date
175
+ => 2013-02-01 18:00:00 -0800
176
+ ```
177
+
178
+
179
+ ```ruby
180
+ r = coinbase.sell!(1)
181
+ r.transfer.code
182
+ => 'RD2OC8AL'
183
+ r.transfer.btc.format
184
+ => "1.00000000 BTC"
185
+ r.transfer.total.format
186
+ => "$17.93"
187
+ r.transfer.payout_date
188
+ => 2013-02-01 18:00:00 -0800
189
+ ```
190
+
191
+ ### Listing Buy/Sell History
192
+
193
+ You can use `transfers` to view past buys and sells.
194
+
195
+ ```ruby
196
+ r = coinbase.transfers
197
+ r.current_page
198
+ => 1
199
+ r.total_count
200
+ => 7
201
+ r.transfers.collect{|t| t.transfer.type }
202
+ => ["Buy", "Buy", ...]
203
+ r.transfers.collect{|t| t.transfer.btc.amount }
204
+ => [0.01, 0.01, ...]
205
+ r.transfers.collect{|t| t.transfer.total.amount }
206
+ => [5.72, 8.35, ...]
207
+ ```
208
+
209
+ ### Create a payment button
210
+
211
+ This will create the code for a payment button (and modal window) that you can use to accept bitcoin on your website. You can read [more about payment buttons here and try a demo](https://coinbase.com/docs/merchant_tools/payment_buttons).
212
+
213
+ The method signature is `def create_button name, price, description=nil, custom=nil, options={}`. The `custom` param will get passed through in [callbacks](https://coinbase.com/docs/merchant_tools/callbacks) to your site. The list of valid `options` [are described here](https://coinbase.com/api/doc/buttons/create.html).
214
+
215
+ ```ruby
216
+ r = coinbase.create_button "Your Order #1234", 42.95.to_money('EUR'), "1 widget at €42.95", "my custom tracking code for this order"
217
+ r.button.code
218
+ => "93865b9cae83706ae59220c013bc0afd"
219
+ r.embed_html
220
+ => "<div class=\"coinbase-button\" data-code=\"93865b9cae83706ae59220c013bc0afd\"></div><script src=\"https://coinbase.com/assets/button.js\" type=\"text/javascript\"></script>"
221
+ ```
222
+
223
+ ### Create an order for a button
224
+
225
+ This will generate an order associated with a button. You can read [more about creating an order for a button here](https://coinbase.com/api/doc/1.0/buttons/create_order.html).
226
+
227
+ ```ruby
228
+ r = coinbase.create_order_for_button "93865b9cae83706ae59220c013bc0afd"
229
+ => "{\"success\"=>true, \"order\"=>{\"id\"=>\"ASXTKPZM\", \"created_at\"=>\"2013-12-13T01:36:47-08:00\", \"status\"=>\"new\", \"total_btc\"=>{\"cents\"=>6859115, \"currency_iso\"=>\"BTC\"}, \"total_native\"=>{\"cents\"=>4295, \"currency_iso\"=>\"EUR\"}, \"custom\"=>\"my custom tracking code for this order\", \"receive_address\"=>\"mpJKwdmJKYjiyfNo26eRp4j6qGwuUUnw9x\", \"button\"=>{\"type\"=>\"buy_now\", \"name\"=>\"Your Order #1234\", \"description\"=>\"1 widget at 42.95\", \"id\"=>\"93865b9cae83706ae59220c013bc0afd\"}, \"transaction\"=>nil}}"
230
+ ```
231
+
232
+ ### Create a new user
233
+
234
+ ```ruby
235
+ r = coinbase.create_user "newuser@example.com", "some password"
236
+ r.user.email
237
+ => "newuser@example.com"
238
+ r.receive_address
239
+ => "mpJKwdmJKYjiyfNo26eRp4j6qGwuUUnw9x"
240
+ ```
241
+
242
+ A receive address is returned also in case you need to send the new user a payment right away.
243
+
244
+ ## Adding new methods
245
+
246
+ You can see a [list of method calls here](https://github.com/coinbase/coinbase-ruby/blob/master/lib/coinbase/client.rb) and how they are implemented. They are a wrapper around the [Coinbase JSON API](https://coinbase.com/api/doc).
247
+
248
+ If there are any methods listed in the [API Reference](https://coinbase.com/api/doc) that don't have an explicit function name in the gem, you can also call `get`, `post`, `put`, or `delete` with a `path` and optional `params` hash for a quick implementation. The raw response will be returned. For example:
249
+
250
+ ```ruby
251
+ coinbase.get('/account/balance').to_hash
252
+ => {"amount"=>"50.00000000", "currency"=>"BTC"}
253
+ ```
254
+
255
+ Or feel free to add a new wrapper method and submit a pull request.
256
+
257
+ ## Security Notes
258
+
259
+ If someone gains access to your API Key they will have complete control of your Coinbase account. This includes the abillity to send all of your bitcoins elsewhere.
260
+
261
+ For this reason, API access is disabled on all Coinbase accounts by default. If you decide to enable API key access you should take precautions to store your API key securely in your application. How to do this is application specific, but it's something you should [research](http://programmers.stackexchange.com/questions/65601/is-it-smart-to-store-application-keys-ids-etc-directly-inside-an-application) if you have never done this before.
262
+
263
+ ## Testing
264
+
265
+ If you'd like to contribute code or modify this gem, you can run the test suite with:
266
+
267
+ ```ruby
268
+ gem install coinbase --dev
269
+ bundle exec rspec # or just 'rspec' may work
270
+ ```
271
+
272
+ ## Contributing
273
+
274
+ 1. Fork this repo and make changes in your own copy
275
+ 2. Add a test if applicable and run the existing tests with `rspec` to make sure they pass
276
+ 3. Commit your changes and push to your fork `git push origin master`
277
+ 4. Create a new pull request and submit it back to us!
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/coinbase.gemspec ADDED
@@ -0,0 +1,31 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'coinbase/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "coinbase"
8
+ gem.version = Coinbase::VERSION
9
+ gem.authors = ["Brian Armstrong"]
10
+ gem.email = [""]
11
+ gem.description = ["Wrapper for the Coinbase Oauth2 API"]
12
+ gem.summary = ["Wrapper for the Coinbase Oauth2 API"]
13
+ gem.homepage = "https://coinbase.com/api/doc"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+
20
+
21
+ # Gems that must be intalled for sift to compile and build
22
+ gem.add_development_dependency "rspec", "~> 2.12"
23
+ gem.add_development_dependency "fakeweb", "~> 1.3.0"
24
+ gem.add_development_dependency "rake"
25
+
26
+ # Gems that must be intalled for sift to work
27
+ gem.add_dependency "httparty", ">= 0.8.3"
28
+ gem.add_dependency "multi_json", ">= 1.3.4"
29
+ gem.add_dependency "money", "= 5.1.1"
30
+ gem.add_dependency "hashie", ">= 1.2.0"
31
+ end
@@ -0,0 +1,44 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBl
3
+ MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
4
+ d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv
5
+ b3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzExMTEwMDAwMDAwWjBlMQswCQYDVQQG
6
+ EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl
7
+ cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwggEi
8
+ MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7c
9
+ JpSIqvTO9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYP
10
+ mDI2dsze3Tyoou9q+yHyUmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+
11
+ wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4
12
+ VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpyoeb6pNnVFzF1roV9Iq4/
13
+ AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whfGHdPAgMB
14
+ AAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW
15
+ BBRF66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYun
16
+ pyGd823IDzANBgkqhkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRC
17
+ dWKuh+vy1dneVrOfzM4UKLkNl2BcEkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTf
18
+ fwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38FnSbNd67IJKusm7Xi+fT8r87cm
19
+ NW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i8b5QZ7dsvfPx
20
+ H2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe
21
+ +o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g==
22
+ -----END CERTIFICATE-----
23
+ -----BEGIN CERTIFICATE-----
24
+ MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
25
+ MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
26
+ d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
27
+ QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT
28
+ MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
29
+ b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG
30
+ 9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB
31
+ CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97
32
+ nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt
33
+ 43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P
34
+ T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4
35
+ gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO
36
+ BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR
37
+ TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw
38
+ DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr
39
+ hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg
40
+ 06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF
41
+ PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls
42
+ YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
43
+ CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
44
+ -----END CERTIFICATE-----
@@ -0,0 +1,229 @@
1
+ require 'httparty'
2
+ require 'multi_json'
3
+ require 'hashie'
4
+ require 'money'
5
+ require 'time'
6
+ require 'securerandom'
7
+
8
+ module Coinbase
9
+ class Client
10
+ include HTTParty
11
+ ssl_ca_file File.expand_path(File.join(File.dirname(__FILE__), 'ca-coinbase.crt'))
12
+
13
+ def initialize(api_key, api_secret, options={})
14
+ @api_key = api_key
15
+ @api_secret = api_secret
16
+
17
+ # defaults
18
+ options[:base_uri] ||= 'https://coinbase.com/api/v1'
19
+ @base_uri = options[:base_uri]
20
+ options[:format] ||= :json
21
+ options.each do |k,v|
22
+ self.class.send k, v
23
+ end
24
+ end
25
+
26
+ # Account
27
+
28
+ def balance options={}
29
+ h = get '/account/balance', options
30
+ h['amount'].to_money(h['currency'])
31
+ end
32
+
33
+ def receive_address options={}
34
+ get '/account/receive_address', options
35
+ end
36
+
37
+ def generate_receive_address options={}
38
+ post '/account/generate_receive_address', options
39
+ end
40
+
41
+ # Buttons
42
+
43
+ def create_button name, price, description=nil, custom=nil, options={}
44
+ options[:button] ||= {}
45
+ options[:button][:name] ||= name
46
+ price = price.to_money unless price.is_a?(Money)
47
+ options[:button][:price_string] ||= price.to_f.to_s
48
+ options[:button][:price_currency_iso] ||= price.currency.iso_code
49
+ options[:button][:description] ||= description
50
+ options[:button][:custom] ||= custom
51
+ r = post '/buttons', options
52
+ if r.success?
53
+ r.embed_html = case options[:button_mode]
54
+ when 'page'
55
+ %[<a href="https://coinbase.com/checkouts/#{r.button.code}" target="_blank"><img alt="#{r.button.text}" src="https://coinbase.com/assets/buttons/#{r.button.style}.png"></a>]
56
+ when 'iframe'
57
+ %[<iframe src="https://coinbase.com/inline_payments/#{r.button.code}" style="width:500px;height:160px;border:none;box-shadow:0 1px 3px rgba(0,0,0,0.25);overflow:hidden;" scrolling="no" allowtransparency="true" frameborder="0"></iframe>]
58
+ else
59
+ %[<div class="coinbase-button" data-code="#{r.button.code}"></div><script src="https://coinbase.com/assets/button.js" type="text/javascript"></script>]
60
+ end
61
+ end
62
+ r
63
+ end
64
+
65
+ def create_order_for_button button_id
66
+ post "/buttons/#{button_id}/create_order"
67
+ end
68
+
69
+ # Transactions
70
+
71
+ def transactions page=1
72
+ r = get '/transactions', {page: page}
73
+ r.transactions ||= []
74
+ r.transactions.each do |t|
75
+ if amt = t.transaction.amount
76
+ t.transaction.amount = amt.amount.to_money(amt.currency)
77
+ end
78
+ end
79
+ r
80
+ end
81
+
82
+ def send_money to, amount, notes=nil, options={}
83
+ options[:transaction] ||= {}
84
+ options[:transaction][:to] ||= to
85
+ amount = amount.to_money unless amount.is_a?(Money)
86
+ options[:transaction][:amount_string] ||= amount.to_f.to_s
87
+ options[:transaction][:amount_currency_iso] ||= amount.currency.iso_code
88
+ options[:transaction][:notes] ||= notes
89
+ r = post '/transactions/send_money', options
90
+ if amt = r.transaction.amount
91
+ r.transaction.amount = amt.amount.to_money(amt.currency)
92
+ end
93
+ r
94
+ end
95
+
96
+ def request_money from, amount, notes=nil, options={}
97
+ options[:transaction] ||= {}
98
+ options[:transaction][:from] ||= from
99
+ amount = amount.to_money unless amount.is_a?(Money)
100
+ options[:transaction][:amount_string] ||= amount.to_f.to_s
101
+ options[:transaction][:amount_currency_iso] ||= amount.currency.iso_code
102
+ options[:transaction][:notes] ||= notes
103
+ r = post '/transactions/request_money', options
104
+ if amt = r.transaction.amount
105
+ r.transaction.amount = amt.amount.to_money(amt.currency)
106
+ end
107
+ r
108
+ end
109
+
110
+ def resend_request transaction_id
111
+ put "/transactions/#{transaction_id}/resend_request"
112
+ end
113
+
114
+ def cancel_request transaction_id
115
+ delete "/transactions/#{transaction_id}/cancel_request"
116
+ end
117
+
118
+ def complete_request transaction_id
119
+ put "/transactions/#{transaction_id}/complete_request"
120
+ end
121
+
122
+ # Users
123
+
124
+ def create_user email, password=nil
125
+ password ||= SecureRandom.urlsafe_base64(12)
126
+ options = {user: {email: email, password: password}}
127
+ post '/users', options
128
+ end
129
+
130
+ # Prices
131
+
132
+ def buy_price qty=1
133
+ r = get '/prices/buy', {qty: qty}
134
+ r['amount'].to_money(r['currency'])
135
+ end
136
+
137
+ def sell_price qty=1
138
+ r = get '/prices/sell', {qty: qty}
139
+ r['amount'].to_money(r['currency'])
140
+ end
141
+
142
+ # Buys
143
+
144
+ def buy! qty
145
+ r = post '/buys', {qty: qty}
146
+ r = convert_money_objects(r)
147
+ r.transfer.payout_date = Time.parse(r.transfer.payout_date) rescue nil
148
+ r
149
+ end
150
+
151
+ # Sells
152
+
153
+ def sell! qty
154
+ r = post '/sells', {qty: qty}
155
+ r = convert_money_objects(r)
156
+ r.transfer.payout_date = Time.parse(r.transfer.payout_date) rescue nil
157
+ r
158
+ end
159
+
160
+ # Transfers
161
+
162
+ def transfers options={}
163
+ r = get '/transfers', options
164
+ r = convert_money_objects(r)
165
+ r.transfers.each do |t|
166
+ t.transfer.payout_date = Time.parse(t.transfer.payout_date) rescue nil
167
+ end
168
+ r
169
+ end
170
+
171
+ # Wrappers for the main HTTP verbs
172
+
173
+ def get(path, options={})
174
+ http_verb :get, path, options
175
+ end
176
+
177
+ def post(path, options={})
178
+ http_verb :post, path, options
179
+ end
180
+
181
+ def put(path, options={})
182
+ http_verb :put, path, options
183
+ end
184
+
185
+ def delete(path, options={})
186
+ http_verb :delete, path, options
187
+ end
188
+
189
+ def http_verb(verb, path, options={})
190
+ nonce = options[:nonce] || (Time.now.to_f * 1e6).to_i
191
+ message = nonce.to_s + @base_uri + path + options.to_json
192
+ signature = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new('sha256'), @api_secret, message)
193
+
194
+ headers = {
195
+ 'ACCESS_KEY' => @api_key,
196
+ 'ACCESS_SIGNATURE' => signature,
197
+ 'ACCESS_NONCE' => nonce.to_s,
198
+ "Content-Type" => "application/json",
199
+ }
200
+
201
+ r = self.class.send(verb, path, {headers: headers, body: options.to_json})
202
+ hash = Hashie::Mash.new(JSON.parse(r.body))
203
+ raise Error.new(hash.error) if hash.error
204
+ raise Error.new(hash.errors.join(", ")) if hash.errors
205
+ hash
206
+ end
207
+
208
+ class Error < StandardError; end
209
+
210
+ private
211
+
212
+ def convert_money_objects obj
213
+ if obj.is_a?(Array)
214
+ obj.each_with_index do |o, i|
215
+ obj[i] = convert_money_objects(o)
216
+ end
217
+ elsif obj.is_a?(Hash)
218
+ if obj[:amount] && (obj[:currency] || obj[:currency_iso])
219
+ obj = obj[:amount].to_money((obj[:currency] || obj[:currency_iso]))
220
+ else
221
+ obj.each do |k,v|
222
+ obj[k] = convert_money_objects(v)
223
+ end
224
+ end
225
+ end
226
+ obj
227
+ end
228
+ end
229
+ end
@@ -0,0 +1,13 @@
1
+ curr = {
2
+ :priority => 1,
3
+ :iso_code => "BTC",
4
+ :name => "Bitcoin",
5
+ :symbol => "BTC",
6
+ :subunit => "Satoshi",
7
+ :subunit_to_unit => 100000000,
8
+ :separator => ".",
9
+ :delimiter => ","
10
+ }
11
+
12
+ Money::Currency.register(curr)
13
+ Money.default_currency = Money::Currency.new("BTC")
@@ -0,0 +1,3 @@
1
+ module Coinbase
2
+ VERSION = "1.3.0"
3
+ end
data/lib/coinbase.rb CHANGED
@@ -1,18 +1,5 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'coinbase/address'
4
- require_relative 'coinbase/asset'
5
- require_relative 'coinbase/balance_map'
6
- require_relative 'coinbase/constants'
7
- require_relative 'coinbase/network'
8
- require_relative 'coinbase/transfer'
9
- require_relative 'coinbase/wallet'
10
- require 'dotenv'
11
-
12
- # The Coinbase SDK.
13
- module Coinbase
14
- # Initializes the Coinbase SDK.
15
- def self.init
16
- Dotenv.load
17
- end
18
- end
1
+ require "json"
2
+ require "money"
3
+ require "coinbase/version"
4
+ require "coinbase/money"
5
+ require "coinbase/client"