coinbase-sdk 0.0.6 → 0.0.8

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 (38) hide show
  1. checksums.yaml +4 -4
  2. data/lib/coinbase/address.rb +73 -19
  3. data/lib/coinbase/asset.rb +80 -56
  4. data/lib/coinbase/balance.rb +10 -6
  5. data/lib/coinbase/client/api/assets_api.rb +91 -0
  6. data/lib/coinbase/client/api/balances_api.rb +97 -0
  7. data/lib/coinbase/client/api/external_addresses_api.rb +242 -0
  8. data/lib/coinbase/client/api/server_signers_api.rb +13 -3
  9. data/lib/coinbase/client/api/stake_api.rb +236 -0
  10. data/lib/coinbase/client/api/transfer_api.rb +114 -0
  11. data/lib/coinbase/client/models/broadcast_trade_request.rb +14 -4
  12. data/lib/coinbase/client/models/build_staking_operation_request.rb +291 -0
  13. data/lib/coinbase/client/models/feature.rb +42 -0
  14. data/lib/coinbase/client/models/fetch_staking_rewards200_response.rb +258 -0
  15. data/lib/coinbase/client/models/fetch_staking_rewards_request.rb +343 -0
  16. data/lib/coinbase/client/models/get_staking_context_request.rb +274 -0
  17. data/lib/coinbase/client/models/partial_eth_staking_context.rb +257 -0
  18. data/lib/coinbase/client/models/request_faucet_funds200_response.rb +222 -0
  19. data/lib/coinbase/client/models/server_signer_list.rb +275 -0
  20. data/lib/coinbase/client/models/staking_context.rb +222 -0
  21. data/lib/coinbase/client/models/staking_context_context.rb +104 -0
  22. data/lib/coinbase/client/models/staking_operation.rb +222 -0
  23. data/lib/coinbase/client/models/staking_reward.rb +308 -0
  24. data/lib/coinbase/client/models/trade.rb +13 -4
  25. data/lib/coinbase/client/models/transaction.rb +45 -1
  26. data/lib/coinbase/client/models/transfer.rb +33 -1
  27. data/lib/coinbase/client/models/wallet.rb +20 -1
  28. data/lib/coinbase/client.rb +14 -0
  29. data/lib/coinbase/constants.rb +2 -27
  30. data/lib/coinbase/errors.rb +50 -62
  31. data/lib/coinbase/network.rb +6 -20
  32. data/lib/coinbase/server_signer.rb +57 -0
  33. data/lib/coinbase/trade.rb +147 -0
  34. data/lib/coinbase/transaction.rb +125 -0
  35. data/lib/coinbase/transfer.rb +22 -55
  36. data/lib/coinbase/wallet.rb +14 -3
  37. data/lib/coinbase.rb +11 -11
  38. metadata +22 -2
@@ -34,9 +34,13 @@ module Coinbase::Client
34
34
  # The ID of the asset being transferred
35
35
  attr_accessor :asset_id
36
36
 
37
+ attr_accessor :asset
38
+
37
39
  # The ID of the transfer
38
40
  attr_accessor :transfer_id
39
41
 
42
+ attr_accessor :transaction
43
+
40
44
  # The unsigned payload of the transfer. This is the payload that needs to be signed by the sender.
41
45
  attr_accessor :unsigned_payload
42
46
 
@@ -80,7 +84,9 @@ module Coinbase::Client
80
84
  :'destination' => :'destination',
81
85
  :'amount' => :'amount',
82
86
  :'asset_id' => :'asset_id',
87
+ :'asset' => :'asset',
83
88
  :'transfer_id' => :'transfer_id',
89
+ :'transaction' => :'transaction',
84
90
  :'unsigned_payload' => :'unsigned_payload',
85
91
  :'signed_payload' => :'signed_payload',
86
92
  :'transaction_hash' => :'transaction_hash',
@@ -102,7 +108,9 @@ module Coinbase::Client
102
108
  :'destination' => :'String',
103
109
  :'amount' => :'String',
104
110
  :'asset_id' => :'String',
111
+ :'asset' => :'Asset',
105
112
  :'transfer_id' => :'String',
113
+ :'transaction' => :'Transaction',
106
114
  :'unsigned_payload' => :'String',
107
115
  :'signed_payload' => :'String',
108
116
  :'transaction_hash' => :'String',
@@ -167,12 +175,24 @@ module Coinbase::Client
167
175
  self.asset_id = nil
168
176
  end
169
177
 
178
+ if attributes.key?(:'asset')
179
+ self.asset = attributes[:'asset']
180
+ else
181
+ self.asset = nil
182
+ end
183
+
170
184
  if attributes.key?(:'transfer_id')
171
185
  self.transfer_id = attributes[:'transfer_id']
172
186
  else
173
187
  self.transfer_id = nil
174
188
  end
175
189
 
190
+ if attributes.key?(:'transaction')
191
+ self.transaction = attributes[:'transaction']
192
+ else
193
+ self.transaction = nil
194
+ end
195
+
176
196
  if attributes.key?(:'unsigned_payload')
177
197
  self.unsigned_payload = attributes[:'unsigned_payload']
178
198
  else
@@ -223,10 +243,18 @@ module Coinbase::Client
223
243
  invalid_properties.push('invalid value for "asset_id", asset_id cannot be nil.')
224
244
  end
225
245
 
246
+ if @asset.nil?
247
+ invalid_properties.push('invalid value for "asset", asset cannot be nil.')
248
+ end
249
+
226
250
  if @transfer_id.nil?
227
251
  invalid_properties.push('invalid value for "transfer_id", transfer_id cannot be nil.')
228
252
  end
229
253
 
254
+ if @transaction.nil?
255
+ invalid_properties.push('invalid value for "transaction", transaction cannot be nil.')
256
+ end
257
+
230
258
  if @unsigned_payload.nil?
231
259
  invalid_properties.push('invalid value for "unsigned_payload", unsigned_payload cannot be nil.')
232
260
  end
@@ -248,7 +276,9 @@ module Coinbase::Client
248
276
  return false if @destination.nil?
249
277
  return false if @amount.nil?
250
278
  return false if @asset_id.nil?
279
+ return false if @asset.nil?
251
280
  return false if @transfer_id.nil?
281
+ return false if @transaction.nil?
252
282
  return false if @unsigned_payload.nil?
253
283
  return false if @status.nil?
254
284
  status_validator = EnumAttributeValidator.new('String', ["pending", "broadcast", "complete", "failed"])
@@ -277,7 +307,9 @@ module Coinbase::Client
277
307
  destination == o.destination &&
278
308
  amount == o.amount &&
279
309
  asset_id == o.asset_id &&
310
+ asset == o.asset &&
280
311
  transfer_id == o.transfer_id &&
312
+ transaction == o.transaction &&
281
313
  unsigned_payload == o.unsigned_payload &&
282
314
  signed_payload == o.signed_payload &&
283
315
  transaction_hash == o.transaction_hash &&
@@ -293,7 +325,7 @@ module Coinbase::Client
293
325
  # Calculates hash code according to all attributes.
294
326
  # @return [Integer] Hash code
295
327
  def hash
296
- [network_id, wallet_id, address_id, destination, amount, asset_id, transfer_id, unsigned_payload, signed_payload, transaction_hash, status].hash
328
+ [network_id, wallet_id, address_id, destination, amount, asset_id, asset, transfer_id, transaction, unsigned_payload, signed_payload, transaction_hash, status].hash
297
329
  end
298
330
 
299
331
  # Builds the object from hash
@@ -23,6 +23,9 @@ module Coinbase::Client
23
23
 
24
24
  attr_accessor :default_address
25
25
 
26
+ # The features enabled for the wallet
27
+ attr_accessor :enabled_features
28
+
26
29
  # The status of the Server-Signer for the wallet if present.
27
30
  attr_accessor :server_signer_status
28
31
 
@@ -54,6 +57,7 @@ module Coinbase::Client
54
57
  :'id' => :'id',
55
58
  :'network_id' => :'network_id',
56
59
  :'default_address' => :'default_address',
60
+ :'enabled_features' => :'enabled_features',
57
61
  :'server_signer_status' => :'server_signer_status'
58
62
  }
59
63
  end
@@ -69,6 +73,7 @@ module Coinbase::Client
69
73
  :'id' => :'String',
70
74
  :'network_id' => :'String',
71
75
  :'default_address' => :'Address',
76
+ :'enabled_features' => :'Array<Feature>',
72
77
  :'server_signer_status' => :'String'
73
78
  }
74
79
  end
@@ -110,6 +115,14 @@ module Coinbase::Client
110
115
  self.default_address = attributes[:'default_address']
111
116
  end
112
117
 
118
+ if attributes.key?(:'enabled_features')
119
+ if (value = attributes[:'enabled_features']).is_a?(Array)
120
+ self.enabled_features = value
121
+ end
122
+ else
123
+ self.enabled_features = nil
124
+ end
125
+
113
126
  if attributes.key?(:'server_signer_status')
114
127
  self.server_signer_status = attributes[:'server_signer_status']
115
128
  end
@@ -128,6 +141,10 @@ module Coinbase::Client
128
141
  invalid_properties.push('invalid value for "network_id", network_id cannot be nil.')
129
142
  end
130
143
 
144
+ if @enabled_features.nil?
145
+ invalid_properties.push('invalid value for "enabled_features", enabled_features cannot be nil.')
146
+ end
147
+
131
148
  invalid_properties
132
149
  end
133
150
 
@@ -137,6 +154,7 @@ module Coinbase::Client
137
154
  warn '[DEPRECATED] the `valid?` method is obsolete'
138
155
  return false if @id.nil?
139
156
  return false if @network_id.nil?
157
+ return false if @enabled_features.nil?
140
158
  server_signer_status_validator = EnumAttributeValidator.new('String', ["pending_seed_creation", "active_seed"])
141
159
  return false unless server_signer_status_validator.valid?(@server_signer_status)
142
160
  true
@@ -160,6 +178,7 @@ module Coinbase::Client
160
178
  id == o.id &&
161
179
  network_id == o.network_id &&
162
180
  default_address == o.default_address &&
181
+ enabled_features == o.enabled_features &&
163
182
  server_signer_status == o.server_signer_status
164
183
  end
165
184
 
@@ -172,7 +191,7 @@ module Coinbase::Client
172
191
  # Calculates hash code according to all attributes.
173
192
  # @return [Integer] Hash code
174
193
  def hash
175
- [id, network_id, default_address, server_signer_status].hash
194
+ [id, network_id, default_address, enabled_features, server_signer_status].hash
176
195
  end
177
196
 
178
197
  # Builds the object from hash
@@ -24,6 +24,7 @@ Coinbase::Client.autoload :Asset, 'coinbase/client/models/asset'
24
24
  Coinbase::Client.autoload :Balance, 'coinbase/client/models/balance'
25
25
  Coinbase::Client.autoload :BroadcastTradeRequest, 'coinbase/client/models/broadcast_trade_request'
26
26
  Coinbase::Client.autoload :BroadcastTransferRequest, 'coinbase/client/models/broadcast_transfer_request'
27
+ Coinbase::Client.autoload :BuildStakingOperationRequest, 'coinbase/client/models/build_staking_operation_request'
27
28
  Coinbase::Client.autoload :CreateAddressRequest, 'coinbase/client/models/create_address_request'
28
29
  Coinbase::Client.autoload :CreateServerSignerRequest, 'coinbase/client/models/create_server_signer_request'
29
30
  Coinbase::Client.autoload :CreateTradeRequest, 'coinbase/client/models/create_trade_request'
@@ -32,14 +33,24 @@ Coinbase::Client.autoload :CreateWalletRequest, 'coinbase/client/models/create_w
32
33
  Coinbase::Client.autoload :CreateWalletRequestWallet, 'coinbase/client/models/create_wallet_request_wallet'
33
34
  Coinbase::Client.autoload :Error, 'coinbase/client/models/error'
34
35
  Coinbase::Client.autoload :FaucetTransaction, 'coinbase/client/models/faucet_transaction'
36
+ Coinbase::Client.autoload :Feature, 'coinbase/client/models/feature'
37
+ Coinbase::Client.autoload :FetchStakingRewards200Response, 'coinbase/client/models/fetch_staking_rewards200_response'
38
+ Coinbase::Client.autoload :FetchStakingRewardsRequest, 'coinbase/client/models/fetch_staking_rewards_request'
39
+ Coinbase::Client.autoload :GetStakingContextRequest, 'coinbase/client/models/get_staking_context_request'
40
+ Coinbase::Client.autoload :PartialEthStakingContext, 'coinbase/client/models/partial_eth_staking_context'
35
41
  Coinbase::Client.autoload :SeedCreationEvent, 'coinbase/client/models/seed_creation_event'
36
42
  Coinbase::Client.autoload :SeedCreationEventResult, 'coinbase/client/models/seed_creation_event_result'
37
43
  Coinbase::Client.autoload :ServerSigner, 'coinbase/client/models/server_signer'
38
44
  Coinbase::Client.autoload :ServerSignerEvent, 'coinbase/client/models/server_signer_event'
39
45
  Coinbase::Client.autoload :ServerSignerEventEvent, 'coinbase/client/models/server_signer_event_event'
40
46
  Coinbase::Client.autoload :ServerSignerEventList, 'coinbase/client/models/server_signer_event_list'
47
+ Coinbase::Client.autoload :ServerSignerList, 'coinbase/client/models/server_signer_list'
41
48
  Coinbase::Client.autoload :SignatureCreationEvent, 'coinbase/client/models/signature_creation_event'
42
49
  Coinbase::Client.autoload :SignatureCreationEventResult, 'coinbase/client/models/signature_creation_event_result'
50
+ Coinbase::Client.autoload :StakingContext, 'coinbase/client/models/staking_context'
51
+ Coinbase::Client.autoload :StakingContextContext, 'coinbase/client/models/staking_context_context'
52
+ Coinbase::Client.autoload :StakingOperation, 'coinbase/client/models/staking_operation'
53
+ Coinbase::Client.autoload :StakingReward, 'coinbase/client/models/staking_reward'
43
54
  Coinbase::Client.autoload :Trade, 'coinbase/client/models/trade'
44
55
  Coinbase::Client.autoload :TradeList, 'coinbase/client/models/trade_list'
45
56
  Coinbase::Client.autoload :Transaction, 'coinbase/client/models/transaction'
@@ -52,7 +63,10 @@ Coinbase::Client.autoload :WalletList, 'coinbase/client/models/wallet_list'
52
63
 
53
64
  # APIs
54
65
  Coinbase::Client.autoload :AddressesApi, 'coinbase/client/api/addresses_api'
66
+ Coinbase::Client.autoload :AssetsApi, 'coinbase/client/api/assets_api'
67
+ Coinbase::Client.autoload :ExternalAddressesApi, 'coinbase/client/api/external_addresses_api'
55
68
  Coinbase::Client.autoload :ServerSignersApi, 'coinbase/client/api/server_signers_api'
69
+ Coinbase::Client.autoload :StakeApi, 'coinbase/client/api/stake_api'
56
70
  Coinbase::Client.autoload :TradesApi, 'coinbase/client/api/trades_api'
57
71
  Coinbase::Client.autoload :TransfersApi, 'coinbase/client/api/transfers_api'
58
72
  Coinbase::Client.autoload :UsersApi, 'coinbase/client/api/users_api'
@@ -4,41 +4,16 @@ require_relative 'asset'
4
4
  require_relative 'network'
5
5
 
6
6
  module Coinbase
7
- # The Assets supported on Base Sepolia by the Coinbase SDK.
8
- ETH = Asset.new(network_id: :base_sepolia, asset_id: :eth, display_name: 'Ether')
9
- USDC = Asset.new(network_id: :base_sepolia, asset_id: :usdc, display_name: 'USD Coin',
10
- address_id: '0x036CbD53842c5426634e7929541eC2318f3dCF7e')
11
- WETH = Asset.new(network_id: :base_sepolia, asset_id: :weth, display_name: 'Wrapped Ether',
12
- address_id: '0x4200000000000000000000000000000000000006')
13
7
  # The Base Sepolia Network.
14
8
  BASE_SEPOLIA = Network.new(
15
9
  network_id: :base_sepolia,
16
10
  display_name: 'Base Sepolia',
17
11
  protocol_family: :evm,
18
12
  is_testnet: true,
19
- assets: [ETH, USDC],
20
13
  native_asset_id: :eth,
21
14
  chain_id: 84_532
22
15
  )
23
16
 
24
- # The amount of Wei per Ether.
25
- WEI_PER_ETHER = 1_000_000_000_000_000_000
26
-
27
- # The amount of Wei per Gwei.
28
- WEI_PER_GWEI = 1_000_000_000
29
-
30
- # The amount of Gwei per Ether.
31
- GWEI_PER_ETHER = 1_000_000_000
32
-
33
- # The amount of atomic units of USDC per USDC.
34
- ATOMIC_UNITS_PER_USDC = 1_000_000
35
-
36
- # A map of supported Asset IDs.
37
- SUPPORTED_ASSET_IDS = {
38
- eth: true, # Ether, the native asset of most EVM networks.
39
- gwei: true, # A medium denomination of Ether, typically used in gas prices.
40
- wei: true, # The smallest denomination of Ether.
41
- usdc: true, # USD Coin, a stablecoin pegged to the US Dollar.
42
- weth: true # Wrapped Ether, the ERC-20 compatible version of Ether.
43
- }.freeze
17
+ # The number of decimal places in Gwei.
18
+ GWEI_DECIMALS = 9
44
19
  end
@@ -6,90 +6,51 @@ require 'json'
6
6
  module Coinbase
7
7
  # A wrapper for API errors to provide more context.
8
8
  class APIError < StandardError
9
- attr_reader :http_code, :api_code, :api_message
9
+ attr_reader :http_code, :api_code, :api_message, :handled
10
10
 
11
11
  # Initializes a new APIError object.
12
12
  # @param err [Coinbase::Client::APIError] The underlying error object.
13
- def initialize(err)
14
- super
13
+ def initialize(err, code: nil, message: nil, unhandled: false)
15
14
  @http_code = err.code
15
+ @api_code = code
16
+ @api_message = message
17
+ @handled = code && message && !unhandled
16
18
 
17
- return unless err.response_body
18
-
19
- body = JSON.parse(err.response_body)
20
- @api_code = body['code']
21
- @api_message = body['message']
19
+ super(err)
22
20
  end
23
21
 
24
22
  # Creates a specific APIError based on the API error code.
25
23
  # @param err [Coinbase::Client::APIError] The underlying error object.
26
24
  # @return [APIError] The specific APIError object.
27
- # rubocop:disable Metrics/MethodLength
28
25
  def self.from_error(err)
29
26
  raise ArgumentError, 'Argument must be a Coinbase::Client::APIError' unless err.is_a? Coinbase::Client::ApiError
30
27
  return APIError.new(err) unless err.response_body
31
28
 
32
- body = JSON.parse(err.response_body)
29
+ begin
30
+ body = JSON.parse(err.response_body)
31
+ rescue JSON::ParserError
32
+ return APIError.new(err)
33
+ end
34
+
35
+ message = body['message']
36
+ code = body['code']
33
37
 
34
- case body['code']
35
- when 'unimplemented'
36
- UnimplementedError.new(err)
37
- when 'unauthorized'
38
- UnauthorizedError.new(err)
39
- when 'internal'
40
- InternalError.new(err)
41
- when 'not_found'
42
- NotFoundError.new(err)
43
- when 'invalid_wallet_id'
44
- InvalidWalletIDError.new(err)
45
- when 'invalid_address_id'
46
- InvalidAddressIDError.new(err)
47
- when 'invalid_wallet'
48
- InvalidWalletError.new(err)
49
- when 'invalid_address'
50
- InvalidAddressError.new(err)
51
- when 'invalid_amount'
52
- InvalidAmountError.new(err)
53
- when 'invalid_transfer_id'
54
- InvalidTransferIDError.new(err)
55
- when 'invalid_page_token'
56
- InvalidPageError.new(err)
57
- when 'invalid_page_limit'
58
- InvalidLimitError.new(err)
59
- when 'already_exists'
60
- AlreadyExistsError.new(err)
61
- when 'malformed_request'
62
- MalformedRequestError.new(err)
63
- when 'unsupported_asset'
64
- UnsupportedAssetError.new(err)
65
- when 'invalid_asset_id'
66
- InvalidAssetIDError.new(err)
67
- when 'invalid_destination'
68
- InvalidDestinationError.new(err)
69
- when 'invalid_network_id'
70
- InvalidNetworkIDError.new(err)
71
- when 'resource_exhausted'
72
- ResourceExhaustedError.new(err)
73
- when 'faucet_limit_reached'
74
- FaucetLimitReachedError.new(err)
75
- when 'invalid_signed_payload'
76
- InvalidSignedPayloadError.new(err)
77
- when 'invalid_transfer_status'
78
- InvalidTransferStatusError.new(err)
38
+ if ERROR_CODE_TO_ERROR_CLASS.key?(code)
39
+ ERROR_CODE_TO_ERROR_CLASS[code].new(err, code: code, message: message)
79
40
  else
80
- APIError.new(err)
41
+ APIError.new(err, code: code, message: message, unhandled: true)
81
42
  end
82
43
  end
83
- # rubocop:enable Metrics/MethodLength
84
44
 
85
- # Returns a String representation of the APIError.
86
- # @return [String] a String representation of the APIError
45
+ # Override to_s to display a friendly error message
87
46
  def to_s
88
- "APIError{http_code: #{@http_code}, api_code: #{@api_code}, api_message: #{@api_message}}"
47
+ # For handled errors, display just the API message as that provides sufficient context.
48
+ return api_message if handled
49
+
50
+ # For unhandled errors, display the full error message
51
+ super
89
52
  end
90
53
 
91
- # Same as to_s.
92
- # @return [String] a String representation of the APIError
93
54
  def inspect
94
55
  to_s
95
56
  end
@@ -117,4 +78,31 @@ module Coinbase
117
78
  class FaucetLimitReachedError < APIError; end
118
79
  class InvalidSignedPayloadError < APIError; end
119
80
  class InvalidTransferStatusError < APIError; end
81
+ class NetworkFeatureUnsupportedError < APIError; end
82
+
83
+ ERROR_CODE_TO_ERROR_CLASS = {
84
+ 'unimplemented' => UnimplementedError,
85
+ 'unauthorized' => UnauthorizedError,
86
+ 'internal' => InternalError,
87
+ 'not_found' => NotFoundError,
88
+ 'invalid_wallet_id' => InvalidWalletIDError,
89
+ 'invalid_address_id' => InvalidAddressIDError,
90
+ 'invalid_wallet' => InvalidWalletError,
91
+ 'invalid_address' => InvalidAddressError,
92
+ 'invalid_amount' => InvalidAmountError,
93
+ 'invalid_transfer_id' => InvalidTransferIDError,
94
+ 'invalid_page_token' => InvalidPageError,
95
+ 'invalid_page_limit' => InvalidLimitError,
96
+ 'already_exists' => AlreadyExistsError,
97
+ 'malformed_request' => MalformedRequestError,
98
+ 'unsupported_asset' => UnsupportedAssetError,
99
+ 'invalid_asset_id' => InvalidAssetIDError,
100
+ 'invalid_destination' => InvalidDestinationError,
101
+ 'invalid_network_id' => InvalidNetworkIDError,
102
+ 'resource_exhausted' => ResourceExhaustedError,
103
+ 'faucet_limit_reached' => FaucetLimitReachedError,
104
+ 'invalid_signed_payload' => InvalidSignedPayloadError,
105
+ 'invalid_transfer_status' => InvalidTransferStatusError,
106
+ 'network_feature_unsupported' => NetworkFeatureUnsupportedError
107
+ }.freeze
120
108
  end
@@ -12,31 +12,15 @@ module Coinbase
12
12
  # @param protocol_family [String] The protocol family to which the Network belongs
13
13
  # (e.g., "evm")
14
14
  # @param is_testnet [Boolean] Whether the Network is a testnet
15
- # @param assets [Array<Asset>] The Assets supported by the Network
16
15
  # @param native_asset_id [String] The ID of the Network's native Asset
17
16
  # @param chain_id [Integer] The Chain ID of the Network
18
- def initialize(network_id:, display_name:, protocol_family:, is_testnet:, assets:, native_asset_id:, chain_id:)
17
+ def initialize(network_id:, display_name:, protocol_family:, is_testnet:, native_asset_id:, chain_id:)
19
18
  @network_id = network_id
20
19
  @display_name = display_name
21
20
  @protocol_family = protocol_family
22
21
  @is_testnet = is_testnet
22
+ @native_asset_id = native_asset_id
23
23
  @chain_id = chain_id
24
-
25
- @asset_map = {}
26
- assets.each do |asset|
27
- @asset_map[asset.asset_id] = asset
28
- end
29
-
30
- raise ArgumentError, 'Native Asset not found' unless @asset_map.key?(native_asset_id)
31
-
32
- @native_asset = @asset_map[native_asset_id]
33
- end
34
-
35
- # Lists the Assets supported by the Network.
36
- #
37
- # @return [Array<Asset>] The Assets supported by the Network
38
- def list_assets
39
- @asset_map.values
40
24
  end
41
25
 
42
26
  # Gets the Asset with the given ID.
@@ -44,12 +28,14 @@ module Coinbase
44
28
  # @param asset_id [Symbol] The ID of the Asset
45
29
  # @return [Asset] The Asset with the given ID
46
30
  def get_asset(asset_id)
47
- @asset_map[asset_id]
31
+ Asset.fetch(@network_id, asset_id)
48
32
  end
49
33
 
50
34
  # Gets the native Asset of the Network.
51
35
  #
52
36
  # @return [Asset] The native Asset of the Network
53
- attr_reader :native_asset
37
+ def native_asset
38
+ @native_asset ||= get_asset(@native_asset_id)
39
+ end
54
40
  end
55
41
  end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'client'
4
+
5
+ module Coinbase
6
+ # A representation of a Server-Signer. Server-Signers are assigned to sign transactions for a Wallet.
7
+ class ServerSigner
8
+ # Returns a new Server-Signer object. Do not use this method directly. Instead, use ServerSigner.default.
9
+ def initialize(model)
10
+ @model = model
11
+ end
12
+
13
+ class << self
14
+ # Returns the default ServerSigner for the CDP Project.
15
+ # @return [Coinbase::ServerSigner] the default Server-Signer
16
+ def default
17
+ response = Coinbase.call_api do
18
+ server_signers_api.list_server_signers
19
+ end
20
+
21
+ raise 'No Server-Signer is associated with the project' if response.data.empty?
22
+
23
+ new(response.data.first)
24
+ end
25
+
26
+ private
27
+
28
+ def server_signers_api
29
+ Coinbase::Client::ServerSignersApi.new(Coinbase.configuration.api_client)
30
+ end
31
+ end
32
+
33
+ # Returns the Server-Signer ID.
34
+ # @return [String] the Server-Signer ID
35
+ def id
36
+ @model.server_signer_id
37
+ end
38
+
39
+ # Returns the IDs of the Wallet's the Server-Signer can sign for.
40
+ # @return [Array<String>] the wallet IDs
41
+ def wallets
42
+ @model.wallets
43
+ end
44
+
45
+ # Returns a string representation of the Server-Signer.
46
+ # @return [String] a string representation of the Server-Signer
47
+ def to_s
48
+ "Coinbase::ServerSigner{server_signer_id: '#{id}', wallets: [#{wallets.join(', ')}]}"
49
+ end
50
+
51
+ # Same as to_s.
52
+ # @return [String] a string representation of the Server-Signer
53
+ def inspect
54
+ to_s
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,147 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'constants'
4
+ require 'bigdecimal'
5
+ require 'eth'
6
+
7
+ module Coinbase
8
+ # A representation of a Trade, which trades an amount of an Asset to another Asset on a Network.
9
+ # The fee is assumed to be paid in the native Asset of the Network.
10
+ # Trades should be created through Wallet#trade or # Address#trade.
11
+ class Trade
12
+ # Returns a new Trade object. Do not use this method directly. Instead, use Wallet#trade or
13
+ # Address#trade.
14
+ # @param model [Coinbase::Client::Trade] The underlying Trade object
15
+ def initialize(model)
16
+ raise unless model.is_a?(Coinbase::Client::Trade)
17
+
18
+ @model = model
19
+ end
20
+
21
+ # Returns the Trade ID.
22
+ # @return [String] The Trade ID
23
+ def id
24
+ @model.trade_id
25
+ end
26
+
27
+ # Returns the Network ID of the Trade.
28
+ # @return [Symbol] The Network ID
29
+ def network_id
30
+ Coinbase.to_sym(@model.network_id)
31
+ end
32
+
33
+ # Returns the Wallet ID of the Trade.
34
+ # @return [String] The Wallet ID
35
+ def wallet_id
36
+ @model.wallet_id
37
+ end
38
+
39
+ # Returns the Address ID of the Trade.
40
+ # @return [String] The Address ID
41
+ def address_id
42
+ @model.address_id
43
+ end
44
+
45
+ # Returns the From Asset ID of the Trade.
46
+ # @return [Symbol] The From Asset ID
47
+ def from_asset_id
48
+ @model.from_asset.asset_id.to_sym
49
+ end
50
+
51
+ # Returns the amount of the from asset for the Trade.
52
+ # @return [BigDecimal] The amount of the from asset
53
+ def from_amount
54
+ BigDecimal(@model.from_amount) / BigDecimal(10).power(@model.from_asset.decimals)
55
+ end
56
+
57
+ # Returns the To Asset ID of the Trade.
58
+ # @return [Symbol] The To Asset ID
59
+ def to_asset_id
60
+ @model.to_asset.asset_id.to_sym
61
+ end
62
+
63
+ # Returns the amount of the to asset for the Trade.
64
+ # @return [BigDecimal] The amount of the to asset
65
+ def to_amount
66
+ BigDecimal(@model.to_amount) / BigDecimal(10).power(@model.to_asset.decimals)
67
+ end
68
+
69
+ # Returns the Trade transaction.
70
+ # @return [Coinbase::Transaction] The Trade transaction
71
+ def transaction
72
+ @transaction ||= Coinbase::Transaction.new(@model.transaction)
73
+ end
74
+
75
+ def approve_transaction
76
+ @approve_transaction ||= @model.approve_transaction ? Coinbase::Transaction.new(@model.approve_transaction) : nil
77
+ end
78
+
79
+ # Returns the status of the Trade.
80
+ # @return [Symbol] The status
81
+ def status
82
+ transaction.status
83
+ end
84
+
85
+ # Waits until the Trade is completed or failed by polling the Network at the given interval. Raises a
86
+ # Timeout::Error if the Trade takes longer than the given timeout.
87
+ # @param interval_seconds [Integer] The interval at which to poll the Network, in seconds
88
+ # @param timeout_seconds [Integer] The maximum amount of time to wait for the Trade to complete, in seconds
89
+ # @return [Trade] The completed Trade object
90
+ def wait!(interval_seconds = 0.2, timeout_seconds = 10)
91
+ start_time = Time.now
92
+
93
+ loop do
94
+ reload
95
+
96
+ # Wait for the trade transaction to be in a terminal state.
97
+ # The approve transaction is optional and must last first, so we don't need to wait for it.
98
+ # We may want to handle a situation where the approve transaction fails and the
99
+ # trade transaction does not ever get broadcast.
100
+ break if transaction.terminal_state?
101
+
102
+ raise Timeout::Error, 'Trade timed out' if Time.now - start_time > timeout_seconds
103
+
104
+ self.sleep interval_seconds
105
+ end
106
+
107
+ self
108
+ end
109
+
110
+ # Reloads the Trade model with the latest version from the server side.
111
+ # @return [Trade] The most recent version of Trade from the server.
112
+ def reload
113
+ @model = Coinbase.call_api do
114
+ trades_api.get_trade(wallet_id, address_id, id)
115
+ end
116
+
117
+ # Update the memoized transaction.
118
+ @transaction = Coinbase::Transaction.new(@model.transaction)
119
+
120
+ # Update the memoized approve transaction if it exists.
121
+ @approve_transaction = @model.approve_transaction ? Coinbase::Transaction.new(@model.approve_transaction) : nil
122
+
123
+ self
124
+ end
125
+
126
+ # Returns a String representation of the Trade.
127
+ # @return [String] a String representation of the Trade
128
+ def to_s
129
+ "Coinbase::Trade{transfer_id: '#{id}', network_id: '#{network_id}', " \
130
+ "address_id: '#{address_id}', from_asset_id: '#{from_asset_id}', " \
131
+ "to_asset_id: '#{to_asset_id}', from_amount: '#{from_amount}', " \
132
+ "to_amount: '#{to_amount}' status: '#{status}'}"
133
+ end
134
+
135
+ # Same as to_s.
136
+ # @return [String] a String representation of the Trade
137
+ def inspect
138
+ to_s
139
+ end
140
+
141
+ private
142
+
143
+ def trades_api
144
+ @trades_api ||= Coinbase::Client::TradesApi.new(Coinbase.configuration.api_client)
145
+ end
146
+ end
147
+ end