coinbase 0.0.1 → 4.0.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.
- checksums.yaml +5 -5
- data/.gitignore +1 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +67 -0
- data/LICENSE.txt +21 -0
- data/README.md +578 -0
- data/Rakefile +7 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/coinbase.gemspec +30 -0
- data/lib/coinbase/wallet/adapters/em_http.rb +64 -0
- data/lib/coinbase/wallet/adapters/net_http.rb +62 -0
- data/lib/coinbase/wallet/api_client.rb +659 -0
- data/lib/coinbase/wallet/api_errors.rb +112 -0
- data/lib/coinbase/wallet/api_response.rb +37 -0
- data/lib/coinbase/wallet/client.rb +98 -0
- data/lib/coinbase/wallet/models/account.rb +187 -0
- data/lib/coinbase/wallet/models/api_object.rb +46 -0
- data/lib/coinbase/wallet/models/checkout.rb +19 -0
- data/lib/coinbase/wallet/models/order.rb +12 -0
- data/lib/coinbase/wallet/models/transaction.rb +21 -0
- data/lib/coinbase/wallet/models/transfer.rb +13 -0
- data/lib/coinbase/wallet/models/user.rb +15 -0
- data/lib/coinbase/wallet/version.rb +5 -0
- data/lib/coinbase/wallet.rb +23 -156
- data/spec/account_spec.rb +193 -0
- data/spec/clients/client_spec.rb +34 -0
- data/spec/clients/oauth_client_spec.rb +56 -0
- data/spec/endpoints_spec.rb +346 -0
- data/spec/error_spec.rb +130 -0
- data/spec/models/api_object_spec.rb +63 -0
- data/spec/models/checkout_spec.rb +52 -0
- data/spec/models/current_user_spec.rb +29 -0
- data/spec/models/order_spec.rb +52 -0
- data/spec/models/request_spec.rb +47 -0
- data/spec/models/transfer_spec.rb +64 -0
- data/spec/models/user_spec.rb +24 -0
- data/spec/spec_helper.rb +13 -0
- metadata +72 -82
- data/lib/coinbase/address.rb +0 -127
- data/lib/coinbase/asset.rb +0 -20
- data/lib/coinbase/balance_map.rb +0 -48
- data/lib/coinbase/constants.rb +0 -38
- data/lib/coinbase/network.rb +0 -55
- data/lib/coinbase/transfer.rb +0 -153
- data/lib/coinbase.rb +0 -18
@@ -0,0 +1,112 @@
|
|
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
|
+
case resp.status
|
19
|
+
when 400
|
20
|
+
case resp.body['errors'].first['id']
|
21
|
+
when 'param_required' then raise ParamRequiredError, format_error(resp)
|
22
|
+
when 'invalid_request' then raise InvalidRequestError, format_error(resp)
|
23
|
+
when 'personal_details_required' then raise PersonalDetailsRequiredError, format_error(resp)
|
24
|
+
end
|
25
|
+
raise BadRequestError, format_error(resp)
|
26
|
+
when 401
|
27
|
+
case resp.body['errors'].first['id']
|
28
|
+
when 'authentication_error' then raise AuthenticationError, format_error(resp)
|
29
|
+
when 'unverified_email' then raise UnverifiedEmailError, format_error(resp)
|
30
|
+
when 'invalid_token' then raise InvalidTokenError, format_error(resp)
|
31
|
+
when 'revoked_token' then raise RevokedTokenError, format_error(resp)
|
32
|
+
when 'expired_token' then raise ExpiredTokenError, format_error(resp)
|
33
|
+
end
|
34
|
+
raise AuthenticationError, format_error(resp)
|
35
|
+
when 402 then raise TwoFactorRequiredError, format_error(resp)
|
36
|
+
when 403 then raise InvalidScopeError, format_error(resp)
|
37
|
+
when 404 then raise NotFoundError, format_error(resp)
|
38
|
+
when 422 then raise ValidationError, format_error(resp)
|
39
|
+
when 429 then raise RateLimitError, format_error(resp)
|
40
|
+
when 500 then raise InternalServerError, format_error(resp)
|
41
|
+
when 503 then raise ServiceUnavailableError, format_error(resp)
|
42
|
+
end
|
43
|
+
|
44
|
+
if resp.status > 400
|
45
|
+
raise APIError, resp.body
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
#
|
50
|
+
# Rest API Errors
|
51
|
+
#
|
52
|
+
class APIError < RuntimeError
|
53
|
+
end
|
54
|
+
|
55
|
+
# Status 400
|
56
|
+
class BadRequestError < APIError
|
57
|
+
end
|
58
|
+
|
59
|
+
class ParamRequiredError < APIError
|
60
|
+
end
|
61
|
+
|
62
|
+
class InvalidRequestError < APIError
|
63
|
+
end
|
64
|
+
|
65
|
+
class PersonalDetailsRequiredError < APIError
|
66
|
+
end
|
67
|
+
|
68
|
+
# Status 401
|
69
|
+
class AuthenticationError < APIError
|
70
|
+
end
|
71
|
+
|
72
|
+
class UnverifiedEmailError < APIError
|
73
|
+
end
|
74
|
+
|
75
|
+
class InvalidTokenError < APIError
|
76
|
+
end
|
77
|
+
|
78
|
+
class RevokedTokenError < APIError
|
79
|
+
end
|
80
|
+
|
81
|
+
class ExpiredTokenError < APIError
|
82
|
+
end
|
83
|
+
|
84
|
+
# Status 402
|
85
|
+
class TwoFactorRequiredError < APIError
|
86
|
+
end
|
87
|
+
|
88
|
+
# Status 403
|
89
|
+
class InvalidScopeError < APIError
|
90
|
+
end
|
91
|
+
|
92
|
+
# Status 404
|
93
|
+
class NotFoundError < APIError
|
94
|
+
end
|
95
|
+
|
96
|
+
# Status 422
|
97
|
+
class ValidationError < APIError
|
98
|
+
end
|
99
|
+
|
100
|
+
# Status 429
|
101
|
+
class RateLimitError < APIError
|
102
|
+
end
|
103
|
+
|
104
|
+
# Status 500
|
105
|
+
class InternalServerError < APIError
|
106
|
+
end
|
107
|
+
|
108
|
+
# Status 503
|
109
|
+
class ServiceUnavailableError < APIError
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,37 @@
|
|
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 headers
|
25
|
+
raise NotImplementedError
|
26
|
+
end
|
27
|
+
|
28
|
+
def status
|
29
|
+
raise NotImplementedError
|
30
|
+
end
|
31
|
+
|
32
|
+
def has_more?
|
33
|
+
body.has_key?('pagination') && body['pagination']['next_uri'] != nil
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,98 @@
|
|
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 |data, 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 |data, resp|
|
68
|
+
out = APIObject.new(self, resp.body)
|
69
|
+
@access_token = out.access_token
|
70
|
+
yield(out, resp) if block_given?
|
71
|
+
end
|
72
|
+
out
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
class AsyncClient < EMHTTPClient
|
77
|
+
def initialize(options={})
|
78
|
+
[ :api_key, :api_secret ].each do |opt|
|
79
|
+
raise unless options.has_key? opt
|
80
|
+
end
|
81
|
+
@api_key = options[:api_key]
|
82
|
+
@api_secret = options[:api_secret]
|
83
|
+
@api_uri = URI.parse(options[:api_url] || BASE_API_URL)
|
84
|
+
end
|
85
|
+
|
86
|
+
def auth_headers(method, path, body)
|
87
|
+
ts = Time.now.to_i.to_s
|
88
|
+
signature = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'),
|
89
|
+
@api_secret,
|
90
|
+
ts + method + path + body.to_s)
|
91
|
+
{ 'CB-ACCESS-KEY' => @api_key,
|
92
|
+
'CB-ACCESS-SIGN' => signature,
|
93
|
+
'CB-ACCESS-TIMESTAMP' => ts,
|
94
|
+
'CB-VERSION' => API_VERSION }
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,187 @@
|
|
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 create_address(params = {})
|
40
|
+
@client.create_address(self['id']) do |data, resp|
|
41
|
+
yield(data, resp) if block_given?
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
#
|
46
|
+
# Transactions
|
47
|
+
#
|
48
|
+
def transactions(params = {})
|
49
|
+
@client.transactions(self['id'], params) do |data, resp|
|
50
|
+
yield(data, resp) if block_given?
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def transaction(transaction_id, params = {})
|
55
|
+
@client.transaction(self['id'], transaction_id, params) do |data, resp|
|
56
|
+
yield(data, resp) if block_given?
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def send(params = {})
|
61
|
+
@client.send(self['id'], params) do |data, resp|
|
62
|
+
yield(data, resp) if block_given?
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def transfer(params = {})
|
67
|
+
@client.transfer(self['id'], params) do |data, resp|
|
68
|
+
yield(data, resp) if block_given?
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def request(params = {})
|
73
|
+
@client.request(self['id'], params) do |data, resp|
|
74
|
+
yield(data, resp) if block_given?
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
#
|
79
|
+
# Buys
|
80
|
+
#
|
81
|
+
def list_buys(params = {})
|
82
|
+
@client.list_buys(self['id'], params) do |data, resp|
|
83
|
+
yield(data, resp) if block_given?
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def list_buy(transaction_id, params = {})
|
88
|
+
@client.list_buy(self['id'], transaction_id, params) do |data, resp|
|
89
|
+
yield(data, resp) if block_given?
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def buy(params = {})
|
94
|
+
@client.buy(self['id'], params) do |data, resp|
|
95
|
+
yield(data, resp) if block_given?
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def commit_buy(transaction_id, params = {})
|
100
|
+
@client.commit_buy(self['id'], transaction_id, params) do |data, resp|
|
101
|
+
yield(data, resp) if block_given?
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
#
|
106
|
+
# Sells
|
107
|
+
#
|
108
|
+
def list_sells(params = {})
|
109
|
+
@client.list_sells(self['id'], params) do |data, resp|
|
110
|
+
yield(data, resp) if block_given?
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def list_sell(transaction_id, params = {})
|
115
|
+
@client.list_sell(self['id'], transaction_id, params) do |data, resp|
|
116
|
+
yield(data, resp) if block_given?
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def sell(params = {})
|
121
|
+
@client.sell(self['id'], params) do |data, resp|
|
122
|
+
yield(data, resp) if block_given?
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def commit_sell(transaction_id, params = {})
|
127
|
+
@client.commit_sell(self['id'], transaction_id, params) do |data, resp|
|
128
|
+
yield(data, resp) if block_given?
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
#
|
133
|
+
# Deposit
|
134
|
+
#
|
135
|
+
def list_deposits(params = {})
|
136
|
+
@client.list_deposits(self['id'], params) do |data, resp|
|
137
|
+
yield(data, resp) if block_given?
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def list_deposit(transaction_id, params = {})
|
142
|
+
@client.list_deposit(self['id'], transaction_id, params) do |data, resp|
|
143
|
+
yield(data, resp) if block_given?
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def deposit(params = {})
|
148
|
+
@client.deposit(self['id'], params) do |data, resp|
|
149
|
+
yield(data, resp) if block_given?
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def commit_deposit(transaction_id, params = {})
|
154
|
+
@client.commit_deposit(self['id'], transaction_id, params) do |data, resp|
|
155
|
+
yield(data, resp) if block_given?
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
#
|
160
|
+
# Withdrawals
|
161
|
+
#
|
162
|
+
def list_withdrawals(params = {})
|
163
|
+
@client.list_withdrawals(self['id'], params) do |data, resp|
|
164
|
+
yield(data, resp) if block_given?
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
def list_withdrawal(transaction_id, params = {})
|
169
|
+
@client.list_withdrawal(self['id'], transaction_id, params) do |data, resp|
|
170
|
+
yield(data, resp) if block_given?
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
def withdraw(params = {})
|
175
|
+
@client.withdraw(self['id'], params) do |data, resp|
|
176
|
+
yield(data, resp) if block_given?
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
def commit_withdrawal(transaction_id, params = {})
|
181
|
+
@client.commit_withdrawal(self['id'], transaction_id, params) do |data, resp|
|
182
|
+
yield(data, resp) if block_given?
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
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 |data, resp|
|
13
|
+
update(data)
|
14
|
+
yield(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 |data, 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 |data, 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,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 |data, resp|
|
9
|
+
yield(data, resp) if block_given?
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def cancel!(params = {})
|
14
|
+
@client.delete("#{self['resource_path']}", params) do |data, resp|
|
15
|
+
yield(data, resp) if block_given?
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
@@ -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(data)
|
10
|
+
yield(data, resp) if block_given?
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|