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
@@ -17,6 +17,17 @@ module Coinbase
17
17
  # The maximum number of addresses in a Wallet.
18
18
  MAX_ADDRESSES = 20
19
19
 
20
+ # A representation of ServerSigner status in a Wallet.
21
+ module ServerSignerStatus
22
+ # The Wallet is awaiting seed creation by the ServerSigner. At this point,
23
+ # the Wallet cannot create addresses or sign transactions.
24
+ PENDING = 'pending_seed_creation'
25
+
26
+ # The Wallet has an associated seed created by the ServerSigner. It is ready
27
+ # to create addresses and sign transactions.
28
+ ACTIVE = 'active_seed'
29
+ end
30
+
20
31
  class << self
21
32
  # Imports a Wallet from previously exported wallet data.
22
33
  # @param data [Coinbase::Wallet::Data] the Wallet data to import
@@ -37,13 +48,18 @@ module Coinbase
37
48
 
38
49
  # Creates a new Wallet on the specified Network and generate a default address for it.
39
50
  # @param network_id [String] (Optional) the ID of the blockchain network. Defaults to 'base-sepolia'.
51
+ # @param interval_seconds [Integer] The interval at which to poll the CDPService for the Wallet to
52
+ # have an active seed, if using a ServerSigner, in seconds
53
+ # @param timeout_seconds [Integer] The maximum amount of time to wait for the ServerSigner to
54
+ # create a seed for the Wallet, in seconds
40
55
  # @return [Coinbase::Wallet] the new Wallet
41
- def create(network_id: 'base-sepolia')
56
+ def create(network_id: 'base-sepolia', interval_seconds: 0.2, timeout_seconds: 20)
42
57
  model = Coinbase.call_api do
43
58
  wallets_api.create_wallet(
44
59
  create_wallet_request: {
45
60
  wallet: {
46
- network_id: network_id
61
+ network_id: network_id,
62
+ use_server_signer: Coinbase.use_server_signer?
47
63
  }
48
64
  }
49
65
  )
@@ -51,13 +67,42 @@ module Coinbase
51
67
 
52
68
  wallet = new(model)
53
69
 
54
- wallet.create_address
70
+ # When used with a ServerSigner, the Signer must first register
71
+ # with the Wallet before addresses can be created.
72
+ wait_for_signer(wallet.id, interval_seconds, timeout_seconds) if Coinbase.use_server_signer?
55
73
 
74
+ wallet.create_address
56
75
  wallet
57
76
  end
58
77
 
59
78
  private
60
79
 
80
+ # Wait_for_signer waits until the ServerSigner has created a seed for the Wallet.
81
+ # Timeout::Error if the ServerSigner takes longer than the given timeout to create the seed.
82
+ # @param wallet_id [string] The ID of the Wallet that is awaiting seed creation.
83
+ # @param interval_seconds [Integer] The interval at which to poll the CDPService, in seconds
84
+ # @param timeout_seconds [Integer] The maximum amount of time to wait for the Signer to create a seed, in seconds
85
+ # @return [Wallet] The completed Wallet object that is ready to create addresses.
86
+ def wait_for_signer(wallet_id, interval_seconds, timeout_seconds)
87
+ start_time = Time.now
88
+
89
+ loop do
90
+ model = Coinbase.call_api do
91
+ wallets_api.get_wallet(wallet_id)
92
+ end
93
+
94
+ return self if model.server_signer_status == ServerSignerStatus::ACTIVE
95
+
96
+ if Time.now - start_time > timeout_seconds
97
+ raise Timeout::Error, 'Wallet creation timed out. Check status of your Server-Signer'
98
+ end
99
+
100
+ self.sleep interval_seconds
101
+ end
102
+
103
+ self
104
+ end
105
+
61
106
  # TODO: Memoize these objects in a thread-safe way at the top-level.
62
107
  def addresses_api
63
108
  Coinbase::Client::AddressesApi.new(Coinbase.configuration.api_client)
@@ -78,12 +123,15 @@ module Coinbase
78
123
  # with the Wallet. If not provided, the Wallet will derive the first default address.
79
124
  # @param client [Jimson::Client] (Optional) The JSON RPC client to use for interacting with the Network
80
125
  def initialize(model, seed: nil, address_models: [])
81
- validate_seed_and_address_models(seed, address_models)
126
+ validate_seed_and_address_models(seed, address_models) unless Coinbase.use_server_signer?
82
127
 
83
128
  @model = model
84
- @master = master_node(seed)
85
129
  @addresses = []
86
- @private_key_index = 0
130
+
131
+ unless Coinbase.use_server_signer?
132
+ @master = master_node(seed)
133
+ @private_key_index = 0
134
+ end
87
135
 
88
136
  derive_addresses(address_models)
89
137
  end
@@ -100,6 +148,12 @@ module Coinbase
100
148
  Coinbase.to_sym(@model.network_id)
101
149
  end
102
150
 
151
+ # Returns the ServerSigner Status of the Wallet.
152
+ # @return [Symbol] The ServerSigner Status
153
+ def server_signer_status
154
+ Coinbase.to_sym(@model.server_signer_status)
155
+ end
156
+
103
157
  # Sets the seed of the Wallet. This seed is used to derive keys and sign transactions.
104
158
  # @param seed [String] The seed to set. Expects a 32-byte hexadecimal with no 0x prefix.
105
159
  def seed=(seed)
@@ -121,16 +175,19 @@ module Coinbase
121
175
  # Creates a new Address in the Wallet.
122
176
  # @return [Address] The new Address
123
177
  def create_address
124
- key = derive_key
125
- attestation = create_attestation(key)
126
- public_key = key.public_key.compressed.unpack1('H*')
178
+ opts = { create_address_request: {} }
127
179
 
128
- opts = {
129
- create_address_request: {
130
- public_key: public_key,
131
- attestation: attestation
180
+ unless Coinbase.use_server_signer?
181
+ key = derive_key
182
+
183
+ opts = {
184
+ create_address_request: {
185
+ public_key: key.public_key.compressed.unpack1('H*'),
186
+ attestation: create_attestation(key)
187
+ }
132
188
  }
133
- }
189
+ end
190
+
134
191
  address_model = Coinbase.call_api do
135
192
  addresses_api.create_address(id, opts)
136
193
  end
@@ -177,30 +234,34 @@ module Coinbase
177
234
  Coinbase::Balance.from_model_and_asset_id(response, asset_id).amount
178
235
  end
179
236
 
180
- # Transfers the given amount of the given Asset to the given address. Only same-Network Transfers are supported.
181
- # Currently only the default_address is used to source the Transfer.
237
+ # Transfers the given amount of the given Asset to the specified address or wallet.
238
+ # Only same-network Transfers are supported. Currently only the default_address is used to source the Transfer.
182
239
  # @param amount [Integer, Float, BigDecimal] The amount of the Asset to send
183
240
  # @param asset_id [Symbol] The ID of the Asset to send
184
241
  # @param destination [Wallet | Address | String] The destination of the transfer. If a Wallet, sends to the Wallet's
185
242
  # default address. If a String, interprets it as the address ID.
186
- # @return [Transfer] The hash of the Transfer transaction.
243
+ # @return [Coinbase::Transfer] The Transfer object.
187
244
  def transfer(amount, asset_id, destination)
188
- if destination.is_a?(Wallet)
189
- raise ArgumentError, 'Transfer must be on the same Network' if destination.network_id != network_id
190
-
191
- destination = destination.default_address.id
192
- elsif destination.is_a?(Address)
193
- raise ArgumentError, 'Transfer must be on the same Network' if destination.network_id != network_id
194
-
195
- destination = destination.id
196
- end
197
-
198
245
  default_address.transfer(amount, asset_id, destination)
199
246
  end
200
247
 
248
+ # Trades the given amount of the given Asset for another Asset.
249
+ # Currently only the default_address is used to source the Trade
250
+ # @param amount [Integer, Float, BigDecimal] The amount of the Asset to send.
251
+ # @param from_asset_id [Symbol] The ID of the Asset to trade from. For Ether, :eth, :gwei, and :wei are supported.
252
+ # @param to_asset_id [Symbol] The ID of the Asset to trade to. For Ether, :eth, :gwei, and :wei are supported.
253
+ # default address. If a String, interprets it as the address ID.
254
+ # @return [Coinbase::Trade] The Trade object.
255
+ def trade(amount, from_asset_id, to_asset_id)
256
+ default_address.trade(amount, from_asset_id, to_asset_id)
257
+ end
258
+
201
259
  # Exports the Wallet's data to a Data object.
202
260
  # @return [Data] The Wallet data
203
261
  def export
262
+ # TODO: Improve this check by relying on the backend data to decide whether a wallet is server-signer backed.
263
+ raise 'Cannot export data for Server-Signer backed Wallet' if Coinbase.use_server_signer?
264
+
204
265
  raise 'Cannot export Wallet without loaded seed' if @master.nil?
205
266
 
206
267
  Data.new(wallet_id: id, seed: @master.seed_hex)
@@ -223,6 +284,87 @@ module Coinbase
223
284
  !@master.nil?
224
285
  end
225
286
 
287
+ # Saves the seed of the Wallet to the given file. Wallets whose seeds are saved this way can be
288
+ # rehydrated using load_seed. A single file can be used for multiple Wallet seeds.
289
+ # This is an insecure method of storing Wallet seeds and should only be used for development purposes.
290
+ #
291
+ # @param file_path [String] The path of the file to save the seed to
292
+ # @param encrypt [bool] (Optional) Whether the seed information persisted to the local file system should be
293
+ # encrypted or not. Data is unencrypted by default.
294
+ # @return [String] A string indicating the success of the operation
295
+ def save_seed!(file_path, encrypt: false)
296
+ raise 'Wallet does not have seed loaded' if @master.nil?
297
+
298
+ existing_seeds_in_store = existing_seeds(file_path)
299
+
300
+ seed_to_store = @master.seed_hex
301
+ auth_tag = ''
302
+ iv = ''
303
+ if encrypt
304
+ cipher = OpenSSL::Cipher.new('aes-256-gcm').encrypt
305
+ cipher.key = OpenSSL::Digest.digest('SHA256', encryption_key)
306
+ iv = cipher.random_iv
307
+ cipher.iv = iv
308
+ cipher.auth_data = ''
309
+ encrypted_data = cipher.update(@master.seed_hex) + cipher.final
310
+ auth_tag = cipher.auth_tag.unpack1('H*')
311
+ iv = iv.unpack1('H*')
312
+ seed_to_store = encrypted_data.unpack1('H*')
313
+ end
314
+
315
+ existing_seeds_in_store[id] = {
316
+ seed: seed_to_store,
317
+ encrypted: encrypt,
318
+ auth_tag: auth_tag,
319
+ iv: iv
320
+ }
321
+
322
+ File.open(file_path, 'w') do |file|
323
+ file.write(JSON.pretty_generate(existing_seeds_in_store))
324
+ end
325
+
326
+ "Successfully saved seed for wallet #{id} to #{file_path}."
327
+ end
328
+
329
+ # Loads the seed of the Wallet from the given file.
330
+ # @param file_path [String] The path of the file to load the seed from
331
+ # @return [String] A string indicating the success of the operation
332
+ def load_seed(file_path)
333
+ raise 'Wallet already has seed loaded' unless @master.nil?
334
+
335
+ existing_seeds_in_store = existing_seeds(file_path)
336
+
337
+ raise ArgumentError, "File #{file_path} does not contain seed data" if existing_seeds_in_store == {}
338
+
339
+ if existing_seeds_in_store[id].nil?
340
+ raise ArgumentError, "File #{file_path} does not contain seed data for wallet #{id}"
341
+ end
342
+
343
+ seed_data = existing_seeds_in_store[id]
344
+ local_seed = seed_data['seed']
345
+
346
+ raise ArgumentError, 'Seed data is malformed' if local_seed.nil? || local_seed == ''
347
+
348
+ if seed_data['encrypted']
349
+ raise ArgumentError, 'Encrypted seed data is malformed' if seed_data['iv'] == '' ||
350
+ seed_data['auth_tag'] == ''
351
+
352
+ cipher = OpenSSL::Cipher.new('aes-256-gcm').decrypt
353
+ cipher.key = OpenSSL::Digest.digest('SHA256', encryption_key)
354
+ iv = [seed_data['iv']].pack('H*')
355
+ cipher.iv = iv
356
+ auth_tag = [seed_data['auth_tag']].pack('H*')
357
+ cipher.auth_tag = auth_tag
358
+ cipher.auth_data = ''
359
+ hex_decoded_data = [seed_data['seed']].pack('H*')
360
+ local_seed = cipher.update(hex_decoded_data) + cipher.final
361
+ end
362
+
363
+ self.seed = local_seed
364
+
365
+ "Successfully loaded seed for wallet #{id} from #{file_path}."
366
+ end
367
+
226
368
  # Returns a String representation of the Wallet.
227
369
  # @return [String] a String representation of the Wallet
228
370
  def to_s
@@ -390,6 +532,25 @@ module Coinbase
390
532
  raise ArgumentError, 'Seed must be empty if address_models are not provided'
391
533
  end
392
534
 
535
+ # Loads the Hash of Wallet seeds from the given file.
536
+ # @param file_path [String] The path of the file to load the seed from
537
+ # @return [Hash<String, Hash>] The Hash of from Wallet IDs to seed data
538
+ def existing_seeds(file_path)
539
+ existing_seed_data = '{}'
540
+ existing_seed_data = File.read(file_path) if File.exist?(file_path)
541
+ existing_seeds = JSON.parse(existing_seed_data)
542
+ raise ArgumentError, "#{file_path} is malformed, must be a valid JSON object" unless existing_seeds.is_a?(Hash)
543
+
544
+ existing_seeds
545
+ end
546
+
547
+ # Returns the shared secret to use for encrypting the seed.
548
+ def encryption_key
549
+ pk = OpenSSL::PKey.read(Coinbase.configuration.api_key_private_key)
550
+ public_key = pk.public_key # use own public key to generate the shared secret.
551
+ pk.dh_compute_key(public_key)
552
+ end
553
+
393
554
  def addresses_api
394
555
  @addresses_api ||= Coinbase::Client::AddressesApi.new(Coinbase.configuration.api_client)
395
556
  end
data/lib/coinbase.rb CHANGED
@@ -11,9 +11,12 @@ require_relative 'coinbase/errors'
11
11
  require_relative 'coinbase/faucet_transaction'
12
12
  require_relative 'coinbase/middleware'
13
13
  require_relative 'coinbase/network'
14
+ require_relative 'coinbase/trade'
14
15
  require_relative 'coinbase/transfer'
16
+ require_relative 'coinbase/transaction'
15
17
  require_relative 'coinbase/user'
16
18
  require_relative 'coinbase/wallet'
19
+ require_relative 'coinbase/server_signer'
17
20
  require 'json'
18
21
 
19
22
  # The Coinbase SDK.
@@ -27,27 +30,33 @@ module Coinbase
27
30
  end
28
31
 
29
32
  # Configures the Coinbase SDK.
33
+ # @return [String] A string indicating successful configuration
30
34
  def self.configure
31
35
  yield(configuration)
32
36
 
33
37
  raise InvalidConfiguration, 'API key private key is not set' unless configuration.api_key_private_key
34
38
  raise InvalidConfiguration, 'API key name is not set' unless configuration.api_key_name
39
+
40
+ 'Successfully configured Coinbase SDK'
35
41
  end
36
42
 
37
43
  # Configures the Coinbase SDK from the given CDP API Key JSON file.
38
44
  # @param file_path [String] (Optional) the path to the CDP API Key JSON file
39
45
  # file in the root directory by default.
40
- def self.configure_from_json(file_path = 'coinbase_cloud_api_key.json')
46
+ # @return [String] A string indicating successful configuration
47
+ def self.configure_from_json(file_path = 'cdp_api_key.json')
41
48
  configuration.from_json(file_path)
42
49
 
43
50
  raise InvalidConfiguration, 'API key private key is not set' unless configuration.api_key_private_key
44
51
  raise InvalidConfiguration, 'API key name is not set' unless configuration.api_key_name
52
+
53
+ 'Successfully configured Coinbase SDK'
45
54
  end
46
55
 
47
56
  # Configuration object for the Coinbase SDK.
48
57
  class Configuration
49
58
  attr_reader :base_sepolia_rpc_url, :base_sepolia_client
50
- attr_accessor :api_url, :api_key_name, :api_key_private_key, :debug_api, :backup_file_path
59
+ attr_accessor :api_url, :api_key_name, :api_key_private_key, :debug_api, :use_server_signer
51
60
 
52
61
  # Initializes the configuration object.
53
62
  def initialize
@@ -55,13 +64,13 @@ module Coinbase
55
64
  @base_sepolia_client = Jimson::Client.new(@base_sepolia_rpc_url)
56
65
  @api_url = 'https://api.cdp.coinbase.com'
57
66
  @debug_api = false
58
- @backup_file_path = 'seeds.json'
67
+ @use_server_signer = false
59
68
  end
60
69
 
61
70
  # Sets configuration values based on the provided CDP API Key JSON file.
62
71
  # @param file_path [String] (Optional) the path to the CDP API Key JSON file
63
72
  # file in the root directory by default.
64
- def from_json(file_path = 'coinbase_cloud_api_key.json')
73
+ def from_json(file_path = 'cdp_api_key.json')
65
74
  # Expand paths to respect shortcuts like ~.
66
75
  file_path = File.expand_path(file_path)
67
76
 
@@ -117,4 +126,10 @@ module Coinbase
117
126
  rescue StandardError => e
118
127
  raise e
119
128
  end
129
+
130
+ # Returns whether to use a server signer to manage private keys.
131
+ # @return [bool] whether to use a server signer to manage private keys.
132
+ def self.use_server_signer?
133
+ Coinbase.configuration.use_server_signer
134
+ end
120
135
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: coinbase-sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yuga Cohler
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-05-20 00:00:00.000000000 Z
11
+ date: 2024-06-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bigdecimal
@@ -192,6 +192,20 @@ dependencies:
192
192
  - - '='
193
193
  - !ruby/object:Gem::Version
194
194
  version: 1.63.1
195
+ - !ruby/object:Gem::Dependency
196
+ name: simplecov
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - ">="
200
+ - !ruby/object:Gem::Version
201
+ version: '0'
202
+ type: :development
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - ">="
207
+ - !ruby/object:Gem::Version
208
+ version: '0'
195
209
  - !ruby/object:Gem::Dependency
196
210
  name: yard
197
211
  requirement: !ruby/object:Gem::Requirement
@@ -234,6 +248,9 @@ files:
234
248
  - lib/coinbase/balance_map.rb
235
249
  - lib/coinbase/client.rb
236
250
  - lib/coinbase/client/api/addresses_api.rb
251
+ - lib/coinbase/client/api/server_signers_api.rb
252
+ - lib/coinbase/client/api/stake_api.rb
253
+ - lib/coinbase/client/api/trades_api.rb
237
254
  - lib/coinbase/client/api/transfers_api.rb
238
255
  - lib/coinbase/client/api/users_api.rb
239
256
  - lib/coinbase/client/api/wallets_api.rb
@@ -245,12 +262,33 @@ files:
245
262
  - lib/coinbase/client/models/address_list.rb
246
263
  - lib/coinbase/client/models/asset.rb
247
264
  - lib/coinbase/client/models/balance.rb
265
+ - lib/coinbase/client/models/broadcast_trade_request.rb
248
266
  - lib/coinbase/client/models/broadcast_transfer_request.rb
267
+ - lib/coinbase/client/models/build_staking_operation_request.rb
249
268
  - lib/coinbase/client/models/create_address_request.rb
269
+ - lib/coinbase/client/models/create_server_signer_request.rb
270
+ - lib/coinbase/client/models/create_trade_request.rb
250
271
  - lib/coinbase/client/models/create_transfer_request.rb
251
272
  - lib/coinbase/client/models/create_wallet_request.rb
273
+ - lib/coinbase/client/models/create_wallet_request_wallet.rb
252
274
  - lib/coinbase/client/models/error.rb
253
275
  - lib/coinbase/client/models/faucet_transaction.rb
276
+ - lib/coinbase/client/models/feature.rb
277
+ - lib/coinbase/client/models/request_faucet_funds200_response.rb
278
+ - lib/coinbase/client/models/seed_creation_event.rb
279
+ - lib/coinbase/client/models/seed_creation_event_result.rb
280
+ - lib/coinbase/client/models/server_signer.rb
281
+ - lib/coinbase/client/models/server_signer_event.rb
282
+ - lib/coinbase/client/models/server_signer_event_event.rb
283
+ - lib/coinbase/client/models/server_signer_event_list.rb
284
+ - lib/coinbase/client/models/server_signer_list.rb
285
+ - lib/coinbase/client/models/signature_creation_event.rb
286
+ - lib/coinbase/client/models/signature_creation_event_result.rb
287
+ - lib/coinbase/client/models/staking_operation.rb
288
+ - lib/coinbase/client/models/trade.rb
289
+ - lib/coinbase/client/models/trade_list.rb
290
+ - lib/coinbase/client/models/transaction.rb
291
+ - lib/coinbase/client/models/transaction_type.rb
254
292
  - lib/coinbase/client/models/transfer.rb
255
293
  - lib/coinbase/client/models/transfer_list.rb
256
294
  - lib/coinbase/client/models/user.rb
@@ -262,6 +300,9 @@ files:
262
300
  - lib/coinbase/faucet_transaction.rb
263
301
  - lib/coinbase/middleware.rb
264
302
  - lib/coinbase/network.rb
303
+ - lib/coinbase/server_signer.rb
304
+ - lib/coinbase/trade.rb
305
+ - lib/coinbase/transaction.rb
265
306
  - lib/coinbase/transfer.rb
266
307
  - lib/coinbase/user.rb
267
308
  - lib/coinbase/wallet.rb