coinbase-sdk 0.0.5 → 0.0.7

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.
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.