coinbase-sdk 0.0.7 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -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