coinbase-sdk 0.0.7 → 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.
@@ -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,92 +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)
79
- when 'network_feature_unsupported'
80
- NetworkFeatureUnsupportedError.new(err)
38
+ if ERROR_CODE_TO_ERROR_CLASS.key?(code)
39
+ ERROR_CODE_TO_ERROR_CLASS[code].new(err, code: code, message: message)
81
40
  else
82
- APIError.new(err)
41
+ APIError.new(err, code: code, message: message, unhandled: true)
83
42
  end
84
43
  end
85
- # rubocop:enable Metrics/MethodLength
86
44
 
87
- # Returns a String representation of the APIError.
88
- # @return [String] a String representation of the APIError
45
+ # Override to_s to display a friendly error message
89
46
  def to_s
90
- "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
91
52
  end
92
53
 
93
- # Same as to_s.
94
- # @return [String] a String representation of the APIError
95
54
  def inspect
96
55
  to_s
97
56
  end
@@ -120,4 +79,30 @@ module Coinbase
120
79
  class InvalidSignedPayloadError < APIError; end
121
80
  class InvalidTransferStatusError < APIError; end
122
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
123
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
@@ -421,9 +421,9 @@ module Coinbase
421
421
  end
422
422
 
423
423
  def address_path_prefix
424
- # TODO: Add support for other networks.
424
+ # TODO: Push this logic to the backend.
425
425
  @address_path_prefix ||= case network_id.to_s.split('_').first
426
- when 'base'
426
+ when 'base', 'ethereum'
427
427
  "m/44'/60'/0'/0"
428
428
  else
429
429
  raise ArgumentError, "Unsupported network ID: #{network_id}"
data/lib/coinbase.rb CHANGED
@@ -55,13 +55,10 @@ module Coinbase
55
55
 
56
56
  # Configuration object for the Coinbase SDK.
57
57
  class Configuration
58
- attr_reader :base_sepolia_rpc_url, :base_sepolia_client
59
58
  attr_accessor :api_url, :api_key_name, :api_key_private_key, :debug_api, :use_server_signer
60
59
 
61
60
  # Initializes the configuration object.
62
61
  def initialize
63
- @base_sepolia_rpc_url = 'https://sepolia.base.org'
64
- @base_sepolia_client = Jimson::Client.new(@base_sepolia_rpc_url)
65
62
  @api_url = 'https://api.cdp.coinbase.com'
66
63
  @debug_api = false
67
64
  @use_server_signer = false
@@ -82,13 +79,6 @@ module Coinbase
82
79
  @api_key_private_key = data['privateKey']
83
80
  end
84
81
 
85
- # Sets the Base Sepolia RPC URL.
86
- # @param new_base_sepolia_rpc_url [String] the new Base Sepolia RPC URL
87
- def base_sepolia_rpc_url=(new_base_sepolia_rpc_url)
88
- @base_sepolia_rpc_url = new_base_sepolia_rpc_url
89
- @base_sepolia_client = Jimson::Client.new(@base_sepolia_rpc_url)
90
- end
91
-
92
82
  # Returns the API client.
93
83
  # @return [Coinbase::Client::ApiClient] the API client
94
84
  def api_client
@@ -109,6 +99,13 @@ module Coinbase
109
99
  value.to_s.gsub('-', '_').to_sym
110
100
  end
111
101
 
102
+ # Converts a network symbol to a string, replacing underscores with hyphens.
103
+ # @param network_sym [Symbol] the network symbol to convert
104
+ # @return [String] the converted string
105
+ def self.normalize_network(network_sym)
106
+ network_sym.to_s.gsub(/_/, '-')
107
+ end
108
+
112
109
  # Loads the default user.
113
110
  # @return [Coinbase::User] the default user
114
111
  def self.load_default_user
@@ -122,7 +119,7 @@ module Coinbase
122
119
  def self.call_api
123
120
  yield
124
121
  rescue Coinbase::Client::ApiError => e
125
- raise Coinbase::APIError.from_error(e)
122
+ raise Coinbase::APIError.from_error(e), cause: nil
126
123
  rescue StandardError => e
127
124
  raise e
128
125
  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.7
4
+ version: 0.0.8
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-06-11 00:00:00.000000000 Z
11
+ date: 2024-06-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bigdecimal
@@ -248,9 +248,13 @@ files:
248
248
  - lib/coinbase/balance_map.rb
249
249
  - lib/coinbase/client.rb
250
250
  - lib/coinbase/client/api/addresses_api.rb
251
+ - lib/coinbase/client/api/assets_api.rb
252
+ - lib/coinbase/client/api/balances_api.rb
253
+ - lib/coinbase/client/api/external_addresses_api.rb
251
254
  - lib/coinbase/client/api/server_signers_api.rb
252
255
  - lib/coinbase/client/api/stake_api.rb
253
256
  - lib/coinbase/client/api/trades_api.rb
257
+ - lib/coinbase/client/api/transfer_api.rb
254
258
  - lib/coinbase/client/api/transfers_api.rb
255
259
  - lib/coinbase/client/api/users_api.rb
256
260
  - lib/coinbase/client/api/wallets_api.rb
@@ -274,6 +278,10 @@ files:
274
278
  - lib/coinbase/client/models/error.rb
275
279
  - lib/coinbase/client/models/faucet_transaction.rb
276
280
  - lib/coinbase/client/models/feature.rb
281
+ - lib/coinbase/client/models/fetch_staking_rewards200_response.rb
282
+ - lib/coinbase/client/models/fetch_staking_rewards_request.rb
283
+ - lib/coinbase/client/models/get_staking_context_request.rb
284
+ - lib/coinbase/client/models/partial_eth_staking_context.rb
277
285
  - lib/coinbase/client/models/request_faucet_funds200_response.rb
278
286
  - lib/coinbase/client/models/seed_creation_event.rb
279
287
  - lib/coinbase/client/models/seed_creation_event_result.rb
@@ -284,7 +292,10 @@ files:
284
292
  - lib/coinbase/client/models/server_signer_list.rb
285
293
  - lib/coinbase/client/models/signature_creation_event.rb
286
294
  - lib/coinbase/client/models/signature_creation_event_result.rb
295
+ - lib/coinbase/client/models/staking_context.rb
296
+ - lib/coinbase/client/models/staking_context_context.rb
287
297
  - lib/coinbase/client/models/staking_operation.rb
298
+ - lib/coinbase/client/models/staking_reward.rb
288
299
  - lib/coinbase/client/models/trade.rb
289
300
  - lib/coinbase/client/models/trade_list.rb
290
301
  - lib/coinbase/client/models/transaction.rb