coinbase 0.0.1 → 4.2.0

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.

Potentially problematic release.


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

Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.travis.yml +7 -0
  4. data/CONTRIBUTING.md +53 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE +201 -0
  7. data/README.md +615 -0
  8. data/Rakefile +6 -0
  9. data/bin/console +14 -0
  10. data/bin/setup +7 -0
  11. data/coinbase.gemspec +26 -0
  12. data/lib/coinbase/util.rb +16 -0
  13. data/lib/coinbase/wallet/adapters/em_http.rb +78 -0
  14. data/lib/coinbase/wallet/adapters/net_http.rb +68 -0
  15. data/lib/coinbase/wallet/api_client.rb +755 -0
  16. data/lib/coinbase/wallet/api_errors.rb +120 -0
  17. data/lib/coinbase/wallet/api_response.rb +41 -0
  18. data/lib/coinbase/wallet/ca-coinbase.crt +78 -0
  19. data/lib/coinbase/wallet/client.rb +101 -0
  20. data/lib/coinbase/wallet/coinbase-callback.pub +14 -0
  21. data/lib/coinbase/wallet/models/account.rb +193 -0
  22. data/lib/coinbase/wallet/models/address.rb +12 -0
  23. data/lib/coinbase/wallet/models/api_object.rb +46 -0
  24. data/lib/coinbase/wallet/models/checkout.rb +19 -0
  25. data/lib/coinbase/wallet/models/order.rb +12 -0
  26. data/lib/coinbase/wallet/models/transaction.rb +21 -0
  27. data/lib/coinbase/wallet/models/transfer.rb +13 -0
  28. data/lib/coinbase/wallet/models/user.rb +15 -0
  29. data/lib/coinbase/wallet/version.rb +5 -0
  30. data/lib/coinbase/wallet.rb +24 -156
  31. data/spec/account_spec.rb +199 -0
  32. data/spec/callback_signature_verification_spec.rb +16 -0
  33. data/spec/clients/client_spec.rb +34 -0
  34. data/spec/clients/oauth_client_spec.rb +56 -0
  35. data/spec/endpoints_spec.rb +352 -0
  36. data/spec/error_spec.rb +137 -0
  37. data/spec/models/address_spec.rb +26 -0
  38. data/spec/models/api_object_spec.rb +63 -0
  39. data/spec/models/checkout_spec.rb +52 -0
  40. data/spec/models/current_user_spec.rb +29 -0
  41. data/spec/models/order_spec.rb +52 -0
  42. data/spec/models/request_spec.rb +47 -0
  43. data/spec/models/transfer_spec.rb +64 -0
  44. data/spec/models/user_spec.rb +24 -0
  45. data/spec/spec_helper.rb +13 -0
  46. metadata +66 -110
  47. data/lib/coinbase/address.rb +0 -127
  48. data/lib/coinbase/asset.rb +0 -20
  49. data/lib/coinbase/balance_map.rb +0 -48
  50. data/lib/coinbase/constants.rb +0 -38
  51. data/lib/coinbase/network.rb +0 -55
  52. data/lib/coinbase/transfer.rb +0 -153
  53. data/lib/coinbase.rb +0 -18
@@ -0,0 +1,120 @@
1
+ module Coinbase
2
+ module Wallet
3
+ def self.format_error(resp)
4
+ error = resp.body && (resp.body['errors'] || resp.body['warnings']).first
5
+ return resp.body unless error
6
+ message = error['message']
7
+ message += " (#{error['url']})" if error["url"]
8
+ message
9
+ end
10
+
11
+ def self.check_response_status(resp)
12
+ (resp.body['warnings'] || []).each do |warning|
13
+ message = "WARNING: #{warning['message']}"
14
+ message += " (#{warning['url']})" if warning["url"]
15
+ $stderr.puts message
16
+ end
17
+
18
+ # OAuth2 errors
19
+ if resp.status >= 400 && resp.body['error']
20
+ raise APIError, resp.body['error_description']
21
+ end
22
+
23
+ # Regular errors
24
+ if resp.body['errors']
25
+ case resp.status
26
+ when 400
27
+ case resp.body['errors'].first['id']
28
+ when 'param_required' then raise ParamRequiredError, format_error(resp)
29
+ when 'invalid_request' then raise InvalidRequestError, format_error(resp)
30
+ when 'personal_details_required' then raise PersonalDetailsRequiredError, format_error(resp)
31
+ end
32
+ raise BadRequestError, format_error(resp)
33
+ when 401
34
+ case resp.body['errors'].first['id']
35
+ when 'authentication_error' then raise AuthenticationError, format_error(resp)
36
+ when 'unverified_email' then raise UnverifiedEmailError, format_error(resp)
37
+ when 'invalid_token' then raise InvalidTokenError, format_error(resp)
38
+ when 'revoked_token' then raise RevokedTokenError, format_error(resp)
39
+ when 'expired_token' then raise ExpiredTokenError, format_error(resp)
40
+ end
41
+ raise AuthenticationError, format_error(resp)
42
+ when 402 then raise TwoFactorRequiredError, format_error(resp)
43
+ when 403 then raise InvalidScopeError, format_error(resp)
44
+ when 404 then raise NotFoundError, format_error(resp)
45
+ when 422 then raise ValidationError, format_error(resp)
46
+ when 429 then raise RateLimitError, format_error(resp)
47
+ when 500 then raise InternalServerError, format_error(resp)
48
+ when 503 then raise ServiceUnavailableError, format_error(resp)
49
+ end
50
+ end
51
+
52
+ if resp.status > 400
53
+ raise APIError, "[#{resp.status}] #{resp.body}"
54
+ end
55
+ end
56
+
57
+ #
58
+ # Rest API Errors
59
+ #
60
+ class APIError < RuntimeError
61
+ end
62
+
63
+ # Status 400
64
+ class BadRequestError < APIError
65
+ end
66
+
67
+ class ParamRequiredError < APIError
68
+ end
69
+
70
+ class InvalidRequestError < APIError
71
+ end
72
+
73
+ class PersonalDetailsRequiredError < APIError
74
+ end
75
+
76
+ # Status 401
77
+ class AuthenticationError < APIError
78
+ end
79
+
80
+ class UnverifiedEmailError < APIError
81
+ end
82
+
83
+ class InvalidTokenError < APIError
84
+ end
85
+
86
+ class RevokedTokenError < APIError
87
+ end
88
+
89
+ class ExpiredTokenError < APIError
90
+ end
91
+
92
+ # Status 402
93
+ class TwoFactorRequiredError < APIError
94
+ end
95
+
96
+ # Status 403
97
+ class InvalidScopeError < APIError
98
+ end
99
+
100
+ # Status 404
101
+ class NotFoundError < APIError
102
+ end
103
+
104
+ # Status 422
105
+ class ValidationError < APIError
106
+ end
107
+
108
+ # Status 429
109
+ class RateLimitError < APIError
110
+ end
111
+
112
+ # Status 500
113
+ class InternalServerError < APIError
114
+ end
115
+
116
+ # Status 503
117
+ class ServiceUnavailableError < APIError
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,41 @@
1
+ module Coinbase
2
+ module Wallet
3
+ # Encapsulate data for an API response
4
+ class APIResponse
5
+ attr_reader :received_at
6
+ attr_accessor :client
7
+ attr_accessor :method
8
+ attr_accessor :params
9
+
10
+ def initialize(resp)
11
+ @received_at = Time.now
12
+ @response = resp
13
+ end
14
+
15
+ def raw
16
+ @response
17
+ end
18
+
19
+ def body
20
+ raise NotImplementedError
21
+ end
22
+ alias_method :data, :body
23
+
24
+ def body=(body)
25
+ raise NotImplementedError
26
+ end
27
+
28
+ def headers
29
+ raise NotImplementedError
30
+ end
31
+
32
+ def status
33
+ raise NotImplementedError
34
+ end
35
+
36
+ def has_more?
37
+ body.has_key?('pagination') && body['pagination']['next_uri'] != nil
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,78 @@
1
+ ## DigiCert High Assurance EV Root CA
2
+ -----BEGIN CERTIFICATE-----
3
+ MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs
4
+ MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
5
+ d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
6
+ ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL
7
+ MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
8
+ LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
9
+ RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm
10
+ +9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW
11
+ PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM
12
+ xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB
13
+ Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3
14
+ hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg
15
+ EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF
16
+ MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA
17
+ FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec
18
+ nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z
19
+ eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF
20
+ hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2
21
+ Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
22
+ vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep
23
+ +OkuE6N36B9K
24
+ -----END CERTIFICATE-----
25
+
26
+ ## DigiCert Global Root CA
27
+ -----BEGIN CERTIFICATE-----
28
+ MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
29
+ MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
30
+ d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
31
+ QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT
32
+ MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
33
+ b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG
34
+ 9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB
35
+ CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97
36
+ nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt
37
+ 43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P
38
+ T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4
39
+ gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO
40
+ BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR
41
+ TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw
42
+ DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr
43
+ hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg
44
+ 06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF
45
+ PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls
46
+ YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
47
+ CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
48
+ -----END CERTIFICATE-----
49
+
50
+ ## VeriSign Class 3 Primary CA - G5 (Backup)
51
+ -----BEGIN CERTIFICATE-----
52
+ MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB
53
+ yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL
54
+ ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp
55
+ U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW
56
+ ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0
57
+ aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCByjEL
58
+ MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW
59
+ ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2ln
60
+ biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp
61
+ U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y
62
+ aXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1
63
+ nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbex
64
+ t0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIz
65
+ SdhDY2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQG
66
+ BO+QueQA5N06tRn/Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+
67
+ rCpSx4/VBEnkjWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/
68
+ NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E
69
+ BAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAH
70
+ BgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy
71
+ aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKv
72
+ MzEzMA0GCSqGSIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzE
73
+ p6B4Eq1iDkVwZMXnl2YtmAl+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y
74
+ 5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKEKQsTb47bDN0lAtukixlE0kF6BWlK
75
+ WE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiCKm0oHw0LxOXnGiYZ
76
+ 4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vEZV8N
77
+ hnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq
78
+ -----END CERTIFICATE-----
@@ -0,0 +1,101 @@
1
+ module Coinbase
2
+ module Wallet
3
+ BASE_API_URL = "https://api.coinbase.com"
4
+ API_VERSION = '2015-06-16'
5
+
6
+ class Client < NetHTTPClient
7
+ def initialize(options={})
8
+ [ :api_key, :api_secret ].each do |opt|
9
+ raise unless options.has_key? opt
10
+ end
11
+ @api_key = options[:api_key]
12
+ @api_secret = options[:api_secret]
13
+ @api_uri = URI.parse(options[:api_url] || BASE_API_URL)
14
+ super(@api_uri, options)
15
+ end
16
+
17
+ def auth_headers(method, path, body)
18
+ ts = Time.now.to_i.to_s
19
+ signature = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'),
20
+ @api_secret,
21
+ ts + method + path + body.to_s)
22
+ { 'CB-ACCESS-KEY' => @api_key,
23
+ 'CB-ACCESS-SIGN' => signature,
24
+ 'CB-ACCESS-TIMESTAMP' => ts,
25
+ 'CB-VERSION' => API_VERSION }
26
+ end
27
+ end
28
+
29
+ class OAuthClient < NetHTTPClient
30
+ attr_accessor :access_token, :refresh_token
31
+
32
+ def initialize(options={})
33
+ raise unless options.has_key? :access_token
34
+ @access_token = options[:access_token]
35
+ @refresh_token = options[:refresh_token]
36
+ @oauth_uri = URI.parse(options[:api_url] || BASE_API_URL)
37
+ super(@oauth_uri, options)
38
+ end
39
+
40
+ def auth_headers(method, path, body)
41
+ { 'Authorization' => "Bearer #{@access_token}",
42
+ 'CB-VERSION' => API_VERSION }
43
+ end
44
+
45
+ def authorize!(redirect_url, params = {})
46
+ raise NotImplementedError
47
+ end
48
+
49
+ def revoke!(params = {})
50
+ params[:token] ||= @access_token
51
+
52
+ out = nil
53
+ post("/oauth/revoke", params) do |resp|
54
+ out = APIObject.new(self, resp.body)
55
+ yield(out, resp) if block_given?
56
+ end
57
+ out
58
+ end
59
+
60
+ def refresh!(params = {})
61
+ params[:grant_type] = 'refresh_token'
62
+ params[:refresh_token] ||= @refresh_token
63
+
64
+ raise "Missing Parameter: refresh_token" unless params.has_key?(:refresh_token)
65
+
66
+ out = nil
67
+ post("/oauth/token", params) do |resp|
68
+ out = APIObject.new(self, resp.body)
69
+ # Update tokens to current instance
70
+ # Developer should always persist them
71
+ @access_token = out.access_token
72
+ @refresh_token = out.refresh_token
73
+ yield(out, resp) if block_given?
74
+ end
75
+ out
76
+ end
77
+ end
78
+
79
+ class AsyncClient < EMHTTPClient
80
+ def initialize(options={})
81
+ [ :api_key, :api_secret ].each do |opt|
82
+ raise unless options.has_key? opt
83
+ end
84
+ @api_key = options[:api_key]
85
+ @api_secret = options[:api_secret]
86
+ @api_uri = URI.parse(options[:api_url] || BASE_API_URL)
87
+ end
88
+
89
+ def auth_headers(method, path, body)
90
+ ts = Time.now.to_i.to_s
91
+ signature = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'),
92
+ @api_secret,
93
+ ts + method + path + body.to_s)
94
+ { 'CB-ACCESS-KEY' => @api_key,
95
+ 'CB-ACCESS-SIGN' => signature,
96
+ 'CB-ACCESS-TIMESTAMP' => ts,
97
+ 'CB-VERSION' => API_VERSION }
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,14 @@
1
+ -----BEGIN PUBLIC KEY-----
2
+ MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA9MsJBuXzFGIh/xkAA9Cy
3
+ QdZKRerV+apyOAWY7sEYV/AJg+AX/tW2SHeZj+3OilNYm5DlBi6ZzDboczmENrFn
4
+ mUXQsecsR5qjdDWb2qYqBkDkoZP02m9o9UmKObR8coKW4ZBw0hEf3fP9OEofG2s7
5
+ Z6PReWFyQffnnecwXJoN22qjjsUtNNKOOo7/l+IyGMVmdzJbMWQS4ybaU9r9Ax0J
6
+ 4QUJSS/S4j4LP+3Z9i2DzIe4+PGa4Nf7fQWLwE45UUp5SmplxBfvEGwYNEsHvmRj
7
+ usIy2ZunSO2CjJ/xGGn9+/57W7/SNVzk/DlDWLaN27hUFLEINlWXeYLBPjw5GGWp
8
+ ieXGVcTaFSLBWX3JbOJ2o2L4MxinXjTtpiKjem9197QXSVZ/zF1DI8tRipsgZWT2
9
+ /UQMqsJoVRXHveY9q9VrCLe97FKAUiohLsskr0USrMCUYvLU9mMw15hwtzZlKY8T
10
+ dMH2Ugqv/CPBuYf1Bc7FAsKJwdC504e8kAUgomi4tKuUo25LPZJMTvMTs/9IsRJv
11
+ I7ibYmVR3xNsVEpupdFcTJYGzOQBo8orHKPFn1jj31DIIKociCwu6m8ICDgLuMHj
12
+ 7bUHIlTzPPT7hRPyBQ1KdyvwxbguqpNhqp1hG2sghgMr0M6KMkUEz38JFElsVrpF
13
+ 4z+EqsFcIZzjkSG16BjjjTkCAwEAAQ==
14
+ -----END PUBLIC KEY-----
@@ -0,0 +1,193 @@
1
+ module Coinbase
2
+ module Wallet
3
+ class Account < APIObject
4
+ def update!(params = {})
5
+ @client.update_account(self['id'], params) do |data, resp|
6
+ update(data)
7
+ yield(data, resp) if block_given?
8
+ end
9
+ end
10
+
11
+ def make_primary!(params = {})
12
+ @client.set_primary_account(self['id'], params) do |data, resp|
13
+ update(data)
14
+ yield(data, resp) if block_given?
15
+ end
16
+ end
17
+
18
+ def delete!(params = {})
19
+ @client.delete_account(self['id'], params) do |data, resp|
20
+ yield(data, resp) if block_given?
21
+ end
22
+ end
23
+
24
+ #
25
+ # Addresses
26
+ #
27
+ def addresses(params = {})
28
+ @client.addresses(self['id'], params) do |data, resp|
29
+ yield(data, resp) if block_given?
30
+ end
31
+ end
32
+
33
+ def address(address_id, params = {})
34
+ @client.address(self['id'], address_id, params) do |data, resp|
35
+ yield(data, resp) if block_given?
36
+ end
37
+ end
38
+
39
+ def address_transactions(address_id, params = {})
40
+ @client.address_transactions(self['id'], address_id, params) do |data, resp|
41
+ yield(data, resp) if block_given?
42
+ end
43
+ end
44
+
45
+ def create_address(params = {})
46
+ @client.create_address(self['id'], params) do |data, resp|
47
+ yield(data, resp) if block_given?
48
+ end
49
+ end
50
+
51
+ #
52
+ # Transactions
53
+ #
54
+ def transactions(params = {})
55
+ @client.transactions(self['id'], params) do |data, resp|
56
+ yield(data, resp) if block_given?
57
+ end
58
+ end
59
+
60
+ def transaction(transaction_id, params = {})
61
+ @client.transaction(self['id'], transaction_id, params) do |data, resp|
62
+ yield(data, resp) if block_given?
63
+ end
64
+ end
65
+
66
+ def send(params = {})
67
+ @client.send(self['id'], params) do |data, resp|
68
+ yield(data, resp) if block_given?
69
+ end
70
+ end
71
+
72
+ def transfer(params = {})
73
+ @client.transfer(self['id'], params) do |data, resp|
74
+ yield(data, resp) if block_given?
75
+ end
76
+ end
77
+
78
+ def request(params = {})
79
+ @client.request(self['id'], params) do |data, resp|
80
+ yield(data, resp) if block_given?
81
+ end
82
+ end
83
+
84
+ #
85
+ # Buys
86
+ #
87
+ def list_buys(params = {})
88
+ @client.list_buys(self['id'], params) do |data, resp|
89
+ yield(data, resp) if block_given?
90
+ end
91
+ end
92
+
93
+ def list_buy(transaction_id, params = {})
94
+ @client.list_buy(self['id'], transaction_id, params) do |data, resp|
95
+ yield(data, resp) if block_given?
96
+ end
97
+ end
98
+
99
+ def buy(params = {})
100
+ @client.buy(self['id'], params) do |data, resp|
101
+ yield(data, resp) if block_given?
102
+ end
103
+ end
104
+
105
+ def commit_buy(transaction_id, params = {})
106
+ @client.commit_buy(self['id'], transaction_id, params) do |data, resp|
107
+ yield(data, resp) if block_given?
108
+ end
109
+ end
110
+
111
+ #
112
+ # Sells
113
+ #
114
+ def list_sells(params = {})
115
+ @client.list_sells(self['id'], params) do |data, resp|
116
+ yield(data, resp) if block_given?
117
+ end
118
+ end
119
+
120
+ def list_sell(transaction_id, params = {})
121
+ @client.list_sell(self['id'], transaction_id, params) do |data, resp|
122
+ yield(data, resp) if block_given?
123
+ end
124
+ end
125
+
126
+ def sell(params = {})
127
+ @client.sell(self['id'], params) do |data, resp|
128
+ yield(data, resp) if block_given?
129
+ end
130
+ end
131
+
132
+ def commit_sell(transaction_id, params = {})
133
+ @client.commit_sell(self['id'], transaction_id, params) do |data, resp|
134
+ yield(data, resp) if block_given?
135
+ end
136
+ end
137
+
138
+ #
139
+ # Deposit
140
+ #
141
+ def list_deposits(params = {})
142
+ @client.list_deposits(self['id'], params) do |data, resp|
143
+ yield(data, resp) if block_given?
144
+ end
145
+ end
146
+
147
+ def list_deposit(transaction_id, params = {})
148
+ @client.list_deposit(self['id'], transaction_id, params) do |data, resp|
149
+ yield(data, resp) if block_given?
150
+ end
151
+ end
152
+
153
+ def deposit(params = {})
154
+ @client.deposit(self['id'], params) do |data, resp|
155
+ yield(data, resp) if block_given?
156
+ end
157
+ end
158
+
159
+ def commit_deposit(transaction_id, params = {})
160
+ @client.commit_deposit(self['id'], transaction_id, params) do |data, resp|
161
+ yield(data, resp) if block_given?
162
+ end
163
+ end
164
+
165
+ #
166
+ # Withdrawals
167
+ #
168
+ def list_withdrawals(params = {})
169
+ @client.list_withdrawals(self['id'], params) do |data, resp|
170
+ yield(data, resp) if block_given?
171
+ end
172
+ end
173
+
174
+ def list_withdrawal(transaction_id, params = {})
175
+ @client.list_withdrawal(self['id'], transaction_id, params) do |data, resp|
176
+ yield(data, resp) if block_given?
177
+ end
178
+ end
179
+
180
+ def withdraw(params = {})
181
+ @client.withdraw(self['id'], params) do |data, resp|
182
+ yield(data, resp) if block_given?
183
+ end
184
+ end
185
+
186
+ def commit_withdrawal(transaction_id, params = {})
187
+ @client.commit_withdrawal(self['id'], transaction_id, params) do |data, resp|
188
+ yield(data, resp) if block_given?
189
+ end
190
+ end
191
+ end
192
+ end
193
+ end
@@ -0,0 +1,12 @@
1
+ module Coinbase
2
+ module Wallet
3
+ class Address < APIObject
4
+ def transactions(params = {})
5
+ @client.get("#{self['resource_path']}/transactions", params) do |resp|
6
+ out = resp.data.map { |item| Transaction.new(self, item) }
7
+ yield(out, resp) if block_given?
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,46 @@
1
+ module Coinbase
2
+ module Wallet
3
+ # Response item abstract model
4
+ class APIObject < Hash
5
+ def initialize(client, data)
6
+ super()
7
+ update(data)
8
+ @client = client
9
+ end
10
+
11
+ def refresh!(params = {})
12
+ @client.get(self['resource_path'], params) do |resp|
13
+ update(resp.data)
14
+ yield(resp.data, resp) if block_given?
15
+ end
16
+ end
17
+
18
+ def update(data)
19
+ return if data.nil?
20
+ data.each { |key, val| self[key] = val } if data.is_a?(Hash)
21
+ end
22
+
23
+ def format(key, val)
24
+ return if val.nil?
25
+ # Looks like a number or currency
26
+ if val.class == Hash
27
+ APIObject.new(@client, val)
28
+ elsif key =~ /_at$/ && (Time.iso8601(val) rescue nil)
29
+ Time.parse(val)
30
+ elsif key == "amount" && val =~ /^.{0,1}\s*[0-9,]*\.{0,1}[0-9]*$/
31
+ BigDecimal(val.gsub(/[^0-9\.]/, ''))
32
+ else
33
+ val
34
+ end
35
+ end
36
+
37
+ def method_missing(method, *args, &blk)
38
+ format(method.to_s, self[method.to_s]) || super
39
+ end
40
+
41
+ def respond_to_missing?(method, include_all = false)
42
+ self.key?(method.to_s) || super
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,19 @@
1
+ module Coinbase
2
+ module Wallet
3
+ class Checkout < APIObject
4
+ def orders(params = {})
5
+ @client.get("#{self['resource_path']}/orders", params) do |resp|
6
+ out = resp.data.map { |item| Order.new(self, item) }
7
+ yield(out, resp) if block_given?
8
+ end
9
+ end
10
+
11
+ def create_order(params = {})
12
+ @client.post("#{self['resource_path']}/orders", params) do |resp|
13
+ out = Order.new(self, resp.data)
14
+ yield(out, resp) if block_given?
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,12 @@
1
+ module Coinbase
2
+ module Wallet
3
+ class Order < APIObject
4
+ def refund!(params = {})
5
+ @client.post("#{self['resource_path']}/refund", params) do |resp|
6
+ update(resp.data)
7
+ yield(resp.data, resp) if block_given?
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,21 @@
1
+ module Coinbase
2
+ module Wallet
3
+ class Transaction < APIObject
4
+ end
5
+
6
+ class Request < Transaction
7
+ def resend!(params = {})
8
+ @client.post("#{self['resource_path']}/resend", params) do |resp|
9
+ yield(resp.data, resp) if block_given?
10
+ end
11
+ end
12
+
13
+ def cancel!(params = {})
14
+ @client.delete("#{self['resource_path']}", params) do |resp|
15
+ yield(resp.data, resp) if block_given?
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+
@@ -0,0 +1,13 @@
1
+ module Coinbase
2
+ module Wallet
3
+ class Transfer < APIObject
4
+ def commit!(params = {})
5
+ @client.post("#{self['resource_path']}/commit", params) do |resp|
6
+ update(resp.data)
7
+ yield(resp.data, resp) if block_given?
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
13
+
@@ -0,0 +1,15 @@
1
+ module Coinbase
2
+ module Wallet
3
+ class User < APIObject
4
+ end
5
+
6
+ class CurrentUser < User
7
+ def update!(params = {})
8
+ @client.update_current_user(params) do |data, resp|
9
+ update(resp.data)
10
+ yield(resp.data, resp) if block_given?
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end