coinbase-sdk 0.0.5 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/lib/coinbase/address.rb +113 -40
  3. data/lib/coinbase/asset.rb +18 -4
  4. data/lib/coinbase/authenticator.rb +1 -1
  5. data/lib/coinbase/client/api/server_signers_api.rb +429 -0
  6. data/lib/coinbase/client/api/stake_api.rb +86 -0
  7. data/lib/coinbase/client/api/trades_api.rb +342 -0
  8. data/lib/coinbase/client/models/broadcast_trade_request.rb +232 -0
  9. data/lib/coinbase/client/models/build_staking_operation_request.rb +291 -0
  10. data/lib/coinbase/client/models/create_address_request.rb +0 -14
  11. data/lib/coinbase/client/models/create_server_signer_request.rb +239 -0
  12. data/lib/coinbase/client/models/create_trade_request.rb +256 -0
  13. data/lib/coinbase/client/models/create_wallet_request.rb +1 -1
  14. data/lib/coinbase/client/models/create_wallet_request_wallet.rb +233 -0
  15. data/lib/coinbase/client/models/feature.rb +42 -0
  16. data/lib/coinbase/client/models/request_faucet_funds200_response.rb +222 -0
  17. data/lib/coinbase/client/models/seed_creation_event.rb +240 -0
  18. data/lib/coinbase/client/models/seed_creation_event_result.rb +274 -0
  19. data/lib/coinbase/client/models/server_signer.rb +235 -0
  20. data/lib/coinbase/client/models/server_signer_event.rb +239 -0
  21. data/lib/coinbase/client/models/server_signer_event_event.rb +105 -0
  22. data/lib/coinbase/client/models/server_signer_event_list.rb +275 -0
  23. data/lib/coinbase/client/models/server_signer_list.rb +275 -0
  24. data/lib/coinbase/client/models/signature_creation_event.rb +363 -0
  25. data/lib/coinbase/client/models/signature_creation_event_result.rb +329 -0
  26. data/lib/coinbase/client/models/staking_operation.rb +222 -0
  27. data/lib/coinbase/client/models/trade.rb +365 -0
  28. data/lib/coinbase/client/models/trade_list.rb +275 -0
  29. data/lib/coinbase/client/models/transaction.rb +338 -0
  30. data/lib/coinbase/client/models/transaction_type.rb +39 -0
  31. data/lib/coinbase/client/models/transfer.rb +33 -1
  32. data/lib/coinbase/client/models/wallet.rb +74 -4
  33. data/lib/coinbase/client.rb +23 -0
  34. data/lib/coinbase/errors.rb +3 -0
  35. data/lib/coinbase/server_signer.rb +57 -0
  36. data/lib/coinbase/trade.rb +147 -0
  37. data/lib/coinbase/transaction.rb +125 -0
  38. data/lib/coinbase/transfer.rb +38 -71
  39. data/lib/coinbase/user.rb +14 -89
  40. data/lib/coinbase/wallet.rb +188 -27
  41. data/lib/coinbase.rb +19 -4
  42. metadata +43 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 98cd32134ee8acb14c9dc018f39e7af188646b546998c4182cd50d7ae75f2816
4
- data.tar.gz: df6ff19c63798ec10f054972aa75edef79fe65ae39c93cbe0941c77db251e5d6
3
+ metadata.gz: 82ed68757d7f8c6d946fed0b3220fe8657d07926bef5f90c50bb279ebb035087
4
+ data.tar.gz: 3b1df1f99ac447f197d0b636ca3d617c670142a42159a42f12a9c60fb2982c0e
5
5
  SHA512:
6
- metadata.gz: a209d25aa72fc185fb667a5ef7b8de617341dba449b0a02b15ad95bc0c434140932353e12258f4665b35ef60e37b5346efca76db811cc5a308cfc69b907f37b8
7
- data.tar.gz: 8856f048ea3ecb664559665e2422d60b6c12d607526aea4bea75f8e8273cf0584b2206e14dcb4e99bdca3436114b03961558be36029b40614d018028f9d41183
6
+ metadata.gz: 0d943a6ff62431d82b72f58ed48fa13f48297c57ef39e7d9efc3afe45141a8d85ffc327f5fbaba9f250c366d398e1961cc61ec2619f3ae7cdaff8012664b6f18
7
+ data.tar.gz: 391942f2797f2c5e8bed4adeff0cfb159f5f8bea90ad4bdebc61a5904929687bbcf73006e14ad1c5f5d9e3d8fb4ee57cbd33ac84af21928fd7b6685004aed63b
@@ -71,59 +71,44 @@ module Coinbase
71
71
  Coinbase::Balance.from_model_and_asset_id(response, asset_id).amount
72
72
  end
73
73
 
74
- # Transfers the given amount of the given Asset to the given address. Only same-Network Transfers are supported.
74
+ # Transfers the given amount of the given Asset to the specified address or wallet.
75
+ # Only same-network Transfers are supported.
75
76
  # @param amount [Integer, Float, BigDecimal] The amount of the Asset to send.
76
77
  # @param asset_id [Symbol] The ID of the Asset to send. For Ether, :eth, :gwei, and :wei are supported.
77
78
  # @param destination [Wallet | Address | String] The destination of the transfer. If a Wallet, sends to the Wallet's
78
79
  # default address. If a String, interprets it as the address ID.
79
- # @return [String] The hash of the Transfer transaction.
80
+ # @return [Coinbase::Transfer] The Transfer object.
80
81
  def transfer(amount, asset_id, destination)
81
- raise 'Cannot transfer from address without private key loaded' if @key.nil?
82
+ destination_address, destination_network = destination_address_and_network(destination)
82
83
 
83
- raise ArgumentError, "Unsupported asset: #{asset_id}" unless Coinbase::Asset.supported?(asset_id)
84
-
85
- if destination.is_a?(Wallet)
86
- raise ArgumentError, 'Transfer must be on the same Network' if destination.network_id != network_id
84
+ validate_can_transfer!(amount, asset_id, destination_network)
87
85
 
88
- destination = destination.default_address.id
89
- elsif destination.is_a?(Address)
90
- raise ArgumentError, 'Transfer must be on the same Network' if destination.network_id != network_id
86
+ transfer = create_transfer(amount, asset_id, destination_address)
91
87
 
92
- destination = destination.id
93
- end
94
-
95
- current_balance = balance(asset_id)
96
- if current_balance < amount
97
- raise ArgumentError, "Insufficient funds: #{amount} requested, but only #{current_balance} available"
98
- end
88
+ # If a server signer is managing keys, it will sign and broadcast the underlying transfer transaction out of band.
89
+ return transfer if Coinbase.use_server_signer?
99
90
 
100
- create_transfer_request = {
101
- amount: Coinbase::Asset.to_atomic_amount(amount, asset_id).to_i.to_s,
102
- network_id: network_id,
103
- asset_id: Coinbase::Asset.primary_denomination(asset_id).to_s,
104
- destination: destination
105
- }
106
-
107
- transfer_model = Coinbase.call_api do
108
- transfers_api.create_transfer(wallet_id, id, create_transfer_request)
109
- end
91
+ broadcast_transfer(transfer, transfer.transaction.sign(@key))
92
+ end
110
93
 
111
- transfer = Coinbase::Transfer.new(transfer_model)
94
+ # Trades the given amount of the given Asset for another Asset.
95
+ # Only same-network Trades are supported.
96
+ # @param amount [Integer, Float, BigDecimal] The amount of the Asset to send.
97
+ # @param from_asset_id [Symbol] The ID of the Asset to trade from. For Ether, :eth, :gwei, and :wei are supported.
98
+ # @param to_asset_id [Symbol] The ID of the Asset to trade to. For Ether, :eth, :gwei, and :wei are supported.
99
+ # @return [Coinbase::Trade] The Trade object.
100
+ def trade(amount, from_asset_id, to_asset_id)
101
+ validate_can_trade!(amount, from_asset_id, to_asset_id)
112
102
 
113
- transaction = transfer.transaction
114
- transaction.sign(@key)
103
+ trade = create_trade(amount, from_asset_id, to_asset_id)
115
104
 
116
- signed_payload = transaction.hex
105
+ # NOTE: Trading does not yet support server signers at this point.
117
106
 
118
- broadcast_transfer_request = {
119
- signed_payload: signed_payload
120
- }
107
+ payloads = { signed_payload: trade.transaction.sign(@key) }
121
108
 
122
- transfer_model = Coinbase.call_api do
123
- transfers_api.broadcast_transfer(wallet_id, id, transfer.id, broadcast_transfer_request)
124
- end
109
+ payloads[:approve_tx_signed_payload] = trade.approve_transaction.sign(@key) unless trade.approve_transaction.nil?
125
110
 
126
- Coinbase::Transfer.new(transfer_model)
111
+ broadcast_trade(trade, **payloads)
127
112
  end
128
113
 
129
114
  # Returns whether the Address has a private key backing it to sign transactions.
@@ -170,12 +155,13 @@ module Coinbase
170
155
  page = nil
171
156
 
172
157
  loop do
173
- puts "fetch transfers page: #{page}"
174
158
  response = Coinbase.call_api do
175
159
  transfers_api.list_transfers(wallet_id, id, { limit: 100, page: page })
176
160
  end
177
161
 
178
- transfers.concat(response.data.map { |transfer| Coinbase::Transfer.new(transfer) }) if response.data
162
+ break if response.data.empty?
163
+
164
+ transfers.concat(response.data.map { |transfer| Coinbase::Transfer.new(transfer) })
179
165
 
180
166
  break unless response.has_more
181
167
 
@@ -194,5 +180,92 @@ module Coinbase
194
180
  def transfers_api
195
181
  @transfers_api ||= Coinbase::Client::TransfersApi.new(Coinbase.configuration.api_client)
196
182
  end
183
+
184
+ def trades_api
185
+ @trades_api ||= Coinbase::Client::TradesApi.new(Coinbase.configuration.api_client)
186
+ end
187
+
188
+ def destination_address_and_network(destination)
189
+ return [destination.default_address.id, destination.network_id] if destination.is_a?(Wallet)
190
+ return [destination.id, destination.network_id] if destination.is_a?(Address)
191
+
192
+ [destination, network_id]
193
+ end
194
+
195
+ def validate_can_transfer!(amount, asset_id, destination_network_id)
196
+ raise 'Cannot transfer from address without private key loaded' unless can_sign? || Coinbase.use_server_signer?
197
+
198
+ raise ArgumentError, "Unsupported asset: #{asset_id}" unless Coinbase::Asset.supported?(asset_id)
199
+
200
+ raise ArgumentError, 'Transfer must be on the same Network' unless destination_network_id == network_id
201
+
202
+ current_balance = balance(asset_id)
203
+
204
+ return unless current_balance < amount
205
+
206
+ raise ArgumentError, "Insufficient funds: #{amount} requested, but only #{current_balance} available"
207
+ end
208
+
209
+ def create_transfer(amount, asset_id, destination)
210
+ create_transfer_request = {
211
+ amount: Coinbase::Asset.to_atomic_amount(amount, asset_id).to_i.to_s,
212
+ network_id: network_id,
213
+ asset_id: Coinbase::Asset.primary_denomination(asset_id).to_s,
214
+ destination: destination
215
+ }
216
+
217
+ transfer_model = Coinbase.call_api do
218
+ transfers_api.create_transfer(wallet_id, id, create_transfer_request)
219
+ end
220
+
221
+ Coinbase::Transfer.new(transfer_model)
222
+ end
223
+
224
+ def broadcast_transfer(transfer, signed_payload)
225
+ transfer_model = Coinbase.call_api do
226
+ transfers_api.broadcast_transfer(wallet_id, id, transfer.id, { signed_payload: signed_payload })
227
+ end
228
+
229
+ Coinbase::Transfer.new(transfer_model)
230
+ end
231
+
232
+ def validate_can_trade!(amount, from_asset_id, to_asset_id)
233
+ raise 'Cannot trade from address without private key loaded' unless can_sign?
234
+
235
+ raise ArgumentError, "Unsupported from asset: #{from_asset_id}" unless Coinbase::Asset.supported?(from_asset_id)
236
+ raise ArgumentError, "Unsupported to asset: #{to_asset_id}" unless Coinbase::Asset.supported?(to_asset_id)
237
+
238
+ current_balance = balance(from_asset_id)
239
+
240
+ return unless current_balance < amount
241
+
242
+ raise ArgumentError, "Insufficient funds: #{amount} requested, but only #{current_balance} available"
243
+ end
244
+
245
+ def create_trade(amount, from_asset_id, to_asset_id)
246
+ create_trade_request = {
247
+ amount: Coinbase::Asset.to_atomic_amount(amount, from_asset_id).to_i.to_s,
248
+ from_asset_id: Coinbase::Asset.primary_denomination(from_asset_id).to_s,
249
+ to_asset_id: Coinbase::Asset.primary_denomination(to_asset_id).to_s
250
+ }
251
+
252
+ trade_model = Coinbase.call_api do
253
+ trades_api.create_trade(wallet_id, id, create_trade_request)
254
+ end
255
+
256
+ Coinbase::Trade.new(trade_model)
257
+ end
258
+
259
+ def broadcast_trade(trade, signed_payload:, approve_tx_signed_payload: nil)
260
+ req = { signed_payload: signed_payload }
261
+
262
+ req[:approve_transaction_signed_payload] = approve_tx_signed_payload unless approve_tx_signed_payload.nil?
263
+
264
+ trade_model = Coinbase.call_api do
265
+ trades_api.broadcast_trade(wallet_id, id, trade.id, req)
266
+ end
267
+
268
+ Coinbase::Trade.new(trade_model)
269
+ end
197
270
  end
198
271
  end
@@ -61,26 +61,40 @@ module Coinbase
61
61
  asset_id
62
62
  end
63
63
 
64
+ def self.from_model(asset_model)
65
+ raise unless asset_model.is_a?(Coinbase::Client::Asset)
66
+
67
+ new(
68
+ network_id: Coinbase.to_sym(asset_model.network_id),
69
+ asset_id: Coinbase.to_sym(asset_model.asset_id),
70
+ address_id: asset_model.contract_address,
71
+ decimals: asset_model.decimals
72
+ )
73
+ end
74
+
64
75
  # Returns a new Asset object. Do not use this method. Instead, use the Asset constants defined in
65
76
  # the Coinbase module.
66
77
  # @param network_id [Symbol] The ID of the Network to which the Asset belongs
67
78
  # @param asset_id [Symbol] The Asset ID
68
- # @param display_name [String] The Asset's display name
79
+ # @param display_name [String] (Optional) The Asset's display name
69
80
  # @param address_id [String] (Optional) The Asset's address ID, if one exists
70
- def initialize(network_id:, asset_id:, display_name:, address_id: nil)
81
+ # @param decimals [Integer] (Optional) The number of decimal places the Asset uses
82
+ def initialize(network_id:, asset_id:, display_name: nil, address_id: nil, decimals: nil)
71
83
  @network_id = network_id
72
84
  @asset_id = asset_id
73
85
  @display_name = display_name
74
86
  @address_id = address_id
87
+ @decimals = decimals
75
88
  end
76
89
 
77
- attr_reader :network_id, :asset_id, :display_name, :address_id
90
+ attr_reader :network_id, :asset_id, :display_name, :address_id, :decimals
78
91
 
79
92
  # Returns a string representation of the Asset.
80
93
  # @return [String] a string representation of the Asset
81
94
  def to_s
82
95
  "Coinbase::Asset{network_id: '#{network_id}', asset_id: '#{asset_id}', display_name: '#{display_name}'" +
83
- (address_id.nil? ? '}' : ", address_id: '#{address_id}'}")
96
+ (address_id.nil? ? '}' : ", address_id: '#{address_id}'}") +
97
+ (decimals.nil? ? '}' : ", decimals: '#{decimals}'}")
84
98
  end
85
99
 
86
100
  # Same as to_s.
@@ -38,7 +38,7 @@ module Coinbase
38
38
 
39
39
  claims = {
40
40
  sub: Coinbase.configuration.api_key_name,
41
- iss: 'coinbase-cloud',
41
+ iss: 'cdp',
42
42
  aud: ['cdp_service'],
43
43
  nbf: Time.now.to_i,
44
44
  exp: Time.now.to_i + 60, # Expiration time: 1 minute from now.