coinbase-sdk 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/lib/coinbase/address.rb +88 -49
  3. data/lib/coinbase/asset.rb +2 -1
  4. data/lib/coinbase/authenticator.rb +52 -0
  5. data/lib/coinbase/balance_map.rb +1 -1
  6. data/lib/coinbase/client/api/addresses_api.rb +385 -0
  7. data/lib/coinbase/client/api/transfers_api.rb +256 -0
  8. data/lib/coinbase/client/api/users_api.rb +79 -0
  9. data/lib/coinbase/client/api/wallets_api.rb +348 -0
  10. data/lib/coinbase/client/api_client.rb +431 -0
  11. data/lib/coinbase/client/api_error.rb +58 -0
  12. data/lib/coinbase/client/configuration.rb +375 -0
  13. data/lib/coinbase/client/models/address.rb +273 -0
  14. data/lib/coinbase/client/models/address_balance_list.rb +275 -0
  15. data/lib/coinbase/client/models/address_list.rb +275 -0
  16. data/lib/coinbase/client/models/asset.rb +260 -0
  17. data/lib/coinbase/client/models/balance.rb +239 -0
  18. data/lib/coinbase/client/models/create_address_request.rb +239 -0
  19. data/lib/coinbase/client/models/create_transfer_request.rb +273 -0
  20. data/lib/coinbase/client/models/create_wallet_request.rb +221 -0
  21. data/lib/coinbase/client/models/error.rb +278 -0
  22. data/lib/coinbase/client/models/transfer.rb +393 -0
  23. data/lib/coinbase/client/models/transfer_list.rb +275 -0
  24. data/lib/coinbase/client/models/user.rb +231 -0
  25. data/lib/coinbase/client/models/wallet.rb +241 -0
  26. data/lib/coinbase/client/models/wallet_list.rb +275 -0
  27. data/lib/coinbase/client/version.rb +15 -0
  28. data/lib/coinbase/client.rb +57 -0
  29. data/lib/coinbase/constants.rb +5 -1
  30. data/lib/coinbase/middleware.rb +21 -0
  31. data/lib/coinbase/network.rb +2 -2
  32. data/lib/coinbase/transfer.rb +69 -54
  33. data/lib/coinbase/user.rb +64 -0
  34. data/lib/coinbase/wallet.rb +146 -54
  35. data/lib/coinbase.rb +73 -9
  36. metadata +74 -6
@@ -0,0 +1,275 @@
1
+ =begin
2
+ #Coinbase Platform API
3
+
4
+ #This is the OpenAPI 3.0 specification for the Coinbase Platform APIs, used in conjunction with the Coinbase Platform SDKs.
5
+
6
+ The version of the OpenAPI document: 0.0.1-alpha
7
+ Contact: yuga.cohler@coinbase.com
8
+ Generated by: https://openapi-generator.tech
9
+ Generator version: 7.5.0
10
+
11
+ =end
12
+
13
+ require 'date'
14
+ require 'time'
15
+
16
+ module Coinbase::Client
17
+ # Paginated list of wallets
18
+ class WalletList
19
+ attr_accessor :data
20
+
21
+ # True if this list has another page of items after this one that can be fetched.
22
+ attr_accessor :has_more
23
+
24
+ # The page token to be used to fetch the next page.
25
+ attr_accessor :next_page
26
+
27
+ # The total number of wallets
28
+ attr_accessor :total_count
29
+
30
+ # Attribute mapping from ruby-style variable name to JSON key.
31
+ def self.attribute_map
32
+ {
33
+ :'data' => :'data',
34
+ :'has_more' => :'has_more',
35
+ :'next_page' => :'next_page',
36
+ :'total_count' => :'total_count'
37
+ }
38
+ end
39
+
40
+ # Returns all the JSON keys this model knows about
41
+ def self.acceptable_attributes
42
+ attribute_map.values
43
+ end
44
+
45
+ # Attribute type mapping.
46
+ def self.openapi_types
47
+ {
48
+ :'data' => :'Array<Wallet>',
49
+ :'has_more' => :'Boolean',
50
+ :'next_page' => :'String',
51
+ :'total_count' => :'Integer'
52
+ }
53
+ end
54
+
55
+ # List of attributes with nullable: true
56
+ def self.openapi_nullable
57
+ Set.new([
58
+ ])
59
+ end
60
+
61
+ # Initializes the object
62
+ # @param [Hash] attributes Model attributes in the form of hash
63
+ def initialize(attributes = {})
64
+ if (!attributes.is_a?(Hash))
65
+ fail ArgumentError, "The input argument (attributes) must be a hash in `Coinbase::Client::WalletList` initialize method"
66
+ end
67
+
68
+ # check to see if the attribute exists and convert string to symbol for hash key
69
+ attributes = attributes.each_with_object({}) { |(k, v), h|
70
+ if (!self.class.attribute_map.key?(k.to_sym))
71
+ fail ArgumentError, "`#{k}` is not a valid attribute in `Coinbase::Client::WalletList`. Please check the name to make sure it's valid. List of attributes: " + self.class.attribute_map.keys.inspect
72
+ end
73
+ h[k.to_sym] = v
74
+ }
75
+
76
+ if attributes.key?(:'data')
77
+ if (value = attributes[:'data']).is_a?(Array)
78
+ self.data = value
79
+ end
80
+ else
81
+ self.data = nil
82
+ end
83
+
84
+ if attributes.key?(:'has_more')
85
+ self.has_more = attributes[:'has_more']
86
+ else
87
+ self.has_more = nil
88
+ end
89
+
90
+ if attributes.key?(:'next_page')
91
+ self.next_page = attributes[:'next_page']
92
+ else
93
+ self.next_page = nil
94
+ end
95
+
96
+ if attributes.key?(:'total_count')
97
+ self.total_count = attributes[:'total_count']
98
+ else
99
+ self.total_count = nil
100
+ end
101
+ end
102
+
103
+ # Show invalid properties with the reasons. Usually used together with valid?
104
+ # @return Array for valid properties with the reasons
105
+ def list_invalid_properties
106
+ warn '[DEPRECATED] the `list_invalid_properties` method is obsolete'
107
+ invalid_properties = Array.new
108
+ if @data.nil?
109
+ invalid_properties.push('invalid value for "data", data cannot be nil.')
110
+ end
111
+
112
+ if @has_more.nil?
113
+ invalid_properties.push('invalid value for "has_more", has_more cannot be nil.')
114
+ end
115
+
116
+ if @next_page.nil?
117
+ invalid_properties.push('invalid value for "next_page", next_page cannot be nil.')
118
+ end
119
+
120
+ if @total_count.nil?
121
+ invalid_properties.push('invalid value for "total_count", total_count cannot be nil.')
122
+ end
123
+
124
+ invalid_properties
125
+ end
126
+
127
+ # Check to see if the all the properties in the model are valid
128
+ # @return true if the model is valid
129
+ def valid?
130
+ warn '[DEPRECATED] the `valid?` method is obsolete'
131
+ return false if @data.nil?
132
+ return false if @has_more.nil?
133
+ return false if @next_page.nil?
134
+ return false if @total_count.nil?
135
+ true
136
+ end
137
+
138
+ # Checks equality by comparing each attribute.
139
+ # @param [Object] Object to be compared
140
+ def ==(o)
141
+ return true if self.equal?(o)
142
+ self.class == o.class &&
143
+ data == o.data &&
144
+ has_more == o.has_more &&
145
+ next_page == o.next_page &&
146
+ total_count == o.total_count
147
+ end
148
+
149
+ # @see the `==` method
150
+ # @param [Object] Object to be compared
151
+ def eql?(o)
152
+ self == o
153
+ end
154
+
155
+ # Calculates hash code according to all attributes.
156
+ # @return [Integer] Hash code
157
+ def hash
158
+ [data, has_more, next_page, total_count].hash
159
+ end
160
+
161
+ # Builds the object from hash
162
+ # @param [Hash] attributes Model attributes in the form of hash
163
+ # @return [Object] Returns the model itself
164
+ def self.build_from_hash(attributes)
165
+ return nil unless attributes.is_a?(Hash)
166
+ attributes = attributes.transform_keys(&:to_sym)
167
+ transformed_hash = {}
168
+ openapi_types.each_pair do |key, type|
169
+ if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil?
170
+ transformed_hash["#{key}"] = nil
171
+ elsif type =~ /\AArray<(.*)>/i
172
+ # check to ensure the input is an array given that the attribute
173
+ # is documented as an array but the input is not
174
+ if attributes[attribute_map[key]].is_a?(Array)
175
+ transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) }
176
+ end
177
+ elsif !attributes[attribute_map[key]].nil?
178
+ transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]])
179
+ end
180
+ end
181
+ new(transformed_hash)
182
+ end
183
+
184
+ # Deserializes the data based on type
185
+ # @param string type Data type
186
+ # @param string value Value to be deserialized
187
+ # @return [Object] Deserialized data
188
+ def self._deserialize(type, value)
189
+ case type.to_sym
190
+ when :Time
191
+ Time.parse(value)
192
+ when :Date
193
+ Date.parse(value)
194
+ when :String
195
+ value.to_s
196
+ when :Integer
197
+ value.to_i
198
+ when :Float
199
+ value.to_f
200
+ when :Boolean
201
+ if value.to_s =~ /\A(true|t|yes|y|1)\z/i
202
+ true
203
+ else
204
+ false
205
+ end
206
+ when :Object
207
+ # generic object (usually a Hash), return directly
208
+ value
209
+ when /\AArray<(?<inner_type>.+)>\z/
210
+ inner_type = Regexp.last_match[:inner_type]
211
+ value.map { |v| _deserialize(inner_type, v) }
212
+ when /\AHash<(?<k_type>.+?), (?<v_type>.+)>\z/
213
+ k_type = Regexp.last_match[:k_type]
214
+ v_type = Regexp.last_match[:v_type]
215
+ {}.tap do |hash|
216
+ value.each do |k, v|
217
+ hash[_deserialize(k_type, k)] = _deserialize(v_type, v)
218
+ end
219
+ end
220
+ else # model
221
+ # models (e.g. Pet) or oneOf
222
+ klass = Coinbase::Client.const_get(type)
223
+ klass.respond_to?(:openapi_any_of) || klass.respond_to?(:openapi_one_of) ? klass.build(value) : klass.build_from_hash(value)
224
+ end
225
+ end
226
+
227
+ # Returns the string representation of the object
228
+ # @return [String] String presentation of the object
229
+ def to_s
230
+ to_hash.to_s
231
+ end
232
+
233
+ # to_body is an alias to to_hash (backward compatibility)
234
+ # @return [Hash] Returns the object in the form of hash
235
+ def to_body
236
+ to_hash
237
+ end
238
+
239
+ # Returns the object in the form of hash
240
+ # @return [Hash] Returns the object in the form of hash
241
+ def to_hash
242
+ hash = {}
243
+ self.class.attribute_map.each_pair do |attr, param|
244
+ value = self.send(attr)
245
+ if value.nil?
246
+ is_nullable = self.class.openapi_nullable.include?(attr)
247
+ next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}"))
248
+ end
249
+
250
+ hash[param] = _to_hash(value)
251
+ end
252
+ hash
253
+ end
254
+
255
+ # Outputs non-array value in the form of hash
256
+ # For object, use to_hash. Otherwise, just return the value
257
+ # @param [Object] value Any valid value
258
+ # @return [Hash] Returns the value in the form of hash
259
+ def _to_hash(value)
260
+ if value.is_a?(Array)
261
+ value.compact.map { |v| _to_hash(v) }
262
+ elsif value.is_a?(Hash)
263
+ {}.tap do |hash|
264
+ value.each { |k, v| hash[k] = _to_hash(v) }
265
+ end
266
+ elsif value.respond_to? :to_hash
267
+ value.to_hash
268
+ else
269
+ value
270
+ end
271
+ end
272
+
273
+ end
274
+
275
+ end
@@ -0,0 +1,15 @@
1
+ =begin
2
+ #Coinbase Platform API
3
+
4
+ #This is the OpenAPI 3.0 specification for the Coinbase Platform APIs, used in conjunction with the Coinbase Platform SDKs.
5
+
6
+ The version of the OpenAPI document: 0.0.1-alpha
7
+ Contact: yuga.cohler@coinbase.com
8
+ Generated by: https://openapi-generator.tech
9
+ Generator version: 7.5.0
10
+
11
+ =end
12
+
13
+ module Coinbase::Client
14
+ VERSION = '0.0.1-alpha'
15
+ end
@@ -0,0 +1,57 @@
1
+ =begin
2
+ #Coinbase Platform API
3
+
4
+ #This is the OpenAPI 3.0 specification for the Coinbase Platform APIs, used in conjunction with the Coinbase Platform SDKs.
5
+
6
+ The version of the OpenAPI document: 0.0.1-alpha
7
+ Contact: yuga.cohler@coinbase.com
8
+ Generated by: https://openapi-generator.tech
9
+ Generator version: 7.5.0
10
+
11
+ =end
12
+
13
+ # Common files
14
+ require 'coinbase/client/api_client'
15
+ require 'coinbase/client/api_error'
16
+ require 'coinbase/client/version'
17
+ require 'coinbase/client/configuration'
18
+
19
+ # Models
20
+ Coinbase::Client.autoload :Address, 'coinbase/client/models/address'
21
+ Coinbase::Client.autoload :AddressBalanceList, 'coinbase/client/models/address_balance_list'
22
+ Coinbase::Client.autoload :AddressList, 'coinbase/client/models/address_list'
23
+ Coinbase::Client.autoload :Asset, 'coinbase/client/models/asset'
24
+ Coinbase::Client.autoload :Balance, 'coinbase/client/models/balance'
25
+ Coinbase::Client.autoload :CreateAddressRequest, 'coinbase/client/models/create_address_request'
26
+ Coinbase::Client.autoload :CreateTransferRequest, 'coinbase/client/models/create_transfer_request'
27
+ Coinbase::Client.autoload :CreateWalletRequest, 'coinbase/client/models/create_wallet_request'
28
+ Coinbase::Client.autoload :Error, 'coinbase/client/models/error'
29
+ Coinbase::Client.autoload :Transfer, 'coinbase/client/models/transfer'
30
+ Coinbase::Client.autoload :TransferList, 'coinbase/client/models/transfer_list'
31
+ Coinbase::Client.autoload :User, 'coinbase/client/models/user'
32
+ Coinbase::Client.autoload :Wallet, 'coinbase/client/models/wallet'
33
+ Coinbase::Client.autoload :WalletList, 'coinbase/client/models/wallet_list'
34
+
35
+ # APIs
36
+ Coinbase::Client.autoload :AddressesApi, 'coinbase/client/api/addresses_api'
37
+ Coinbase::Client.autoload :TransfersApi, 'coinbase/client/api/transfers_api'
38
+ Coinbase::Client.autoload :UsersApi, 'coinbase/client/api/users_api'
39
+ Coinbase::Client.autoload :WalletsApi, 'coinbase/client/api/wallets_api'
40
+
41
+ module Coinbase::Client
42
+ class << self
43
+ # Customize default settings for the SDK using block.
44
+ # Coinbase::Client.configure do |config|
45
+ # config.username = "xxx"
46
+ # config.password = "xxx"
47
+ # end
48
+ # If no block given, return the default Configuration object.
49
+ def configure
50
+ if block_given?
51
+ yield(Configuration.default)
52
+ else
53
+ Configuration.default
54
+ end
55
+ end
56
+ end
57
+ end
@@ -29,10 +29,14 @@ module Coinbase
29
29
  # The amount of Gwei per Ether.
30
30
  GWEI_PER_ETHER = 1_000_000_000
31
31
 
32
+ # The amount of atomic units of USDC per USDC.
33
+ ATOMIC_UNITS_PER_USDC = 1_000_000
34
+
32
35
  # A map of supported Asset IDs.
33
36
  SUPPORTED_ASSET_IDS = {
34
37
  eth: true, # Ether, the native asset of most EVM networks.
35
38
  gwei: true, # A medium denomination of Ether, typically used in gas prices.
36
- wei: true # The smallest denomination of Ether.
39
+ wei: true, # The smallest denomination of Ether.
40
+ usdc: true # USD Coin, a stablecoin pegged to the US Dollar.
37
41
  }.freeze
38
42
  end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'authenticator'
4
+ require_relative 'client/configuration'
5
+ require 'faraday'
6
+
7
+ module Coinbase
8
+ # A module for middleware that can be used with Faraday.
9
+ module Middleware
10
+ Faraday::Request.register_middleware authenticator: -> { Coinbase::Authenticator }
11
+
12
+ # Returns the default middleware configuration for the Coinbase SDK.
13
+ def self.config
14
+ Coinbase::Client::Configuration.default.tap do |config|
15
+ config.debugging = true
16
+ config.host = Coinbase.configuration.api_url
17
+ config.request(:authenticator)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -5,8 +5,8 @@ module Coinbase
5
5
  class Network
6
6
  attr_reader :chain_id
7
7
 
8
- # Returns a new Network object.
9
- #
8
+ # Returns a new Network object. Do not use this method directly. Instead, use the Network constants defined in
9
+ # the Coinbase module.
10
10
  # @param network_id [Symbol] The Network ID
11
11
  # @param display_name [String] The Network's display name
12
12
  # @param protocol_family [String] The protocol family to which the Network belongs
@@ -3,15 +3,14 @@
3
3
  require_relative 'constants'
4
4
  require 'bigdecimal'
5
5
  require 'eth'
6
+ require 'json'
6
7
 
7
8
  module Coinbase
8
9
  # A representation of a Transfer, which moves an amount of an Asset from
9
10
  # a user-controlled Wallet to another address. The fee is assumed to be paid
10
- # in the native Asset of the Network. Currently only ETH transfers are supported. Transfers
11
- # should be created through {link:Wallet#transfer} or {link:Address#transfer}.
11
+ # in the native Asset of the Network. Transfers should be created through Wallet#transfer or
12
+ # Address#transfer.
12
13
  class Transfer
13
- attr_reader :network_id, :wallet_id, :from_address_id, :amount, :asset_id, :to_address_id
14
-
15
14
  # A representation of a Transfer status.
16
15
  module Status
17
16
  # The Transfer is awaiting being broadcast to the Network. At this point, transaction
@@ -29,28 +28,59 @@ module Coinbase
29
28
  FAILED = :failed
30
29
  end
31
30
 
32
- # Returns a new Transfer object.
33
- # @param network_id [Symbol] The ID of the Network on which the Transfer originated
34
- # @param wallet_id [String] The ID of the Wallet from which the Transfer originated
35
- # @param from_address_id [String] The ID of the address from which the Transfer originated
36
- # @param amount [Integer, Float, BigDecimal] The amount of the Asset to send. Integers are interpreted as
37
- # the smallest denomination of the Asset (e.g. Wei for Ether). Floats and BigDecimals are interpreted as the Asset
38
- # itself (e.g. Ether).
39
- # @param asset_id [Symbol] The ID of the Asset being transferred. Currently only ETH is supported.
40
- # @param to_address_id [String] The address to which the Transfer is being sent
41
- # @param client [Jimson::Client] (Optional) The JSON RPC client to use for interacting with the Network
42
- def initialize(network_id, wallet_id, from_address_id, amount, asset_id, to_address_id,
43
- client: Jimson::Client.new(Coinbase.base_sepolia_rpc_url))
44
-
45
- raise ArgumentError, "Unsupported asset: #{asset_id}" if asset_id != :eth
46
-
47
- @network_id = network_id
48
- @wallet_id = wallet_id
49
- @from_address_id = from_address_id
50
- @amount = normalize_eth_amount(amount)
51
- @asset_id = asset_id
52
- @to_address_id = to_address_id
53
- @client = client
31
+ # Returns a new Transfer object. Do not use this method directly. Instead, use Wallet#transfer or
32
+ # Address#transfer.
33
+ # @param model [Coinbase::Client::Transfer] The underlying Transfer object
34
+ def initialize(model)
35
+ @model = model
36
+ end
37
+
38
+ # Returns the Transfer ID.
39
+ # @return [String] The Transfer ID
40
+ def transfer_id
41
+ @model.transfer_id
42
+ end
43
+
44
+ # Returns the Network ID of the Transfer.
45
+ # @return [Symbol] The Network ID
46
+ def network_id
47
+ Coinbase.to_sym(@model.network_id)
48
+ end
49
+
50
+ # Returns the Wallet ID of the Transfer.
51
+ # @return [String] The Wallet ID
52
+ def wallet_id
53
+ @model.wallet_id
54
+ end
55
+
56
+ # Returns the From Address ID of the Transfer.
57
+ # @return [String] The From Address ID
58
+ def from_address_id
59
+ @model.address_id
60
+ end
61
+
62
+ # Returns the Destination Address ID of the Transfer.
63
+ # @return [String] The Destination Address ID
64
+ def destination_address_id
65
+ @model.destination
66
+ end
67
+
68
+ # Returns the Asset ID of the Transfer.
69
+ # @return [Symbol] The Asset ID
70
+ def asset_id
71
+ @model.asset_id.to_sym
72
+ end
73
+
74
+ # Returns the amount of the asset for the Transfer.
75
+ # @return [BigDecimal] The amount in units of ETH
76
+ def amount
77
+ BigDecimal(@model.amount) / BigDecimal(Coinbase::WEI_PER_ETHER.to_s)
78
+ end
79
+
80
+ # Returns the Unsigned Payload of the Transfer.
81
+ # @return [String] The Unsigned Payload
82
+ def unsigned_payload
83
+ @model.unsigned_payload
54
84
  end
55
85
 
56
86
  # Returns the underlying Transfer transaction, creating it if it has not been yet.
@@ -58,18 +88,19 @@ module Coinbase
58
88
  def transaction
59
89
  return @transaction unless @transaction.nil?
60
90
 
61
- nonce = @client.eth_getTransactionCount(@from_address_id.to_s, 'latest').to_i(16)
62
- gas_price = @client.eth_gasPrice.to_i(16)
91
+ raw_payload = [unsigned_payload].pack('H*')
92
+ parsed_payload = JSON.parse(raw_payload)
63
93
 
64
94
  params = {
65
- chain_id: BASE_SEPOLIA.chain_id, # TODO: Don't hardcode Base Sepolia.
66
- nonce: nonce,
67
- priority_fee: gas_price, # TODO: Optimize this.
68
- max_gas_fee: gas_price,
69
- gas_limit: 21_000, # TODO: Handle multiple currencies.
70
- from: Eth::Address.new(@from_address_id),
71
- to: Eth::Address.new(@to_address_id),
72
- value: (@amount * Coinbase::WEI_PER_ETHER).to_i
95
+ chain_id: parsed_payload['chainId'].to_i(16),
96
+ nonce: parsed_payload['nonce'].to_i(16),
97
+ priority_fee: parsed_payload['maxPriorityFeePerGas'].to_i(16),
98
+ max_gas_fee: parsed_payload['maxFeePerGas'].to_i(16),
99
+ gas_limit: parsed_payload['gas'].to_i(16), # TODO: Handle multiple currencies.
100
+ from: Eth::Address.new(from_address_id),
101
+ to: Eth::Address.new(parsed_payload['to']),
102
+ value: parsed_payload['value'].to_i(16),
103
+ data: parsed_payload['input'] || ''
73
104
  }
74
105
 
75
106
  @transaction = Eth::Tx::Eip1559.new(Eth::Tx.validate_eip1559_params(params))
@@ -87,7 +118,7 @@ module Coinbase
87
118
  return Status::PENDING
88
119
  end
89
120
 
90
- onchain_transaction = @client.eth_getTransactionByHash(transaction_hash)
121
+ onchain_transaction = Coinbase.configuration.base_sepolia_client.eth_getTransactionByHash(transaction_hash)
91
122
 
92
123
  if onchain_transaction.nil?
93
124
  # If the transaction has not been broadcast, it is still pending.
@@ -97,7 +128,7 @@ module Coinbase
97
128
  # broadcast.
98
129
  Status::BROADCAST
99
130
  else
100
- transaction_receipt = @client.eth_getTransactionReceipt(transaction_hash)
131
+ transaction_receipt = Coinbase.configuration.base_sepolia_client.eth_getTransactionReceipt(transaction_hash)
101
132
 
102
133
  if transaction_receipt['status'].to_i(16) == 1
103
134
  Status::COMPLETE
@@ -133,21 +164,5 @@ module Coinbase
133
164
  rescue Eth::Signature::SignatureError
134
165
  nil
135
166
  end
136
-
137
- private
138
-
139
- # Normalizes the given Ether amount into a BigDecimal.
140
- # @param amount [Integer, Float, BigDecimal] The amount to normalize
141
- # @return [BigDecimal] The normalized amount
142
- def normalize_eth_amount(amount)
143
- case amount
144
- when BigDecimal
145
- amount
146
- when Integer, Float
147
- BigDecimal(amount.to_s)
148
- else
149
- raise ArgumentError, "Invalid amount: #{amount}"
150
- end
151
- end
152
167
  end
153
168
  end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'client'
4
+ require_relative 'wallet'
5
+
6
+ module Coinbase
7
+ # A representation of a User. Users have Wallets, which can hold balances of Assets. Access the default User through
8
+ # Coinbase#default_user.
9
+ class User
10
+ # Returns a new User object. Do not use this method directly. Instead, use Coinbase#default_user.
11
+ # @param model [Coinbase::Client::User] the underlying User object
12
+ def initialize(model)
13
+ @model = model
14
+ end
15
+
16
+ # Returns the User ID.
17
+ # @return [String] the User ID
18
+ def user_id
19
+ @model.id
20
+ end
21
+
22
+ # Creates a new Wallet belonging to the User.
23
+ # @return [Coinbase::Wallet] the new Wallet
24
+ def create_wallet
25
+ create_wallet_request = {
26
+ wallet: {
27
+ # TODO: Don't hardcode this.
28
+ network_id: 'base-sepolia'
29
+ }
30
+ }
31
+ opts = { create_wallet_request: create_wallet_request }
32
+
33
+ model = wallets_api.create_wallet(opts)
34
+
35
+ Wallet.new(model)
36
+ end
37
+
38
+ # Imports a Wallet belonging to the User.
39
+ # @param data [Coinbase::Wallet::Data] the Wallet data to import
40
+ # @return [Coinbase::Wallet] the imported Wallet
41
+ def import_wallet(data)
42
+ model = wallets_api.get_wallet(data.wallet_id)
43
+ address_count = addresses_api.list_addresses(model.id).total_count
44
+ Wallet.new(model, seed: data.seed, address_count: address_count)
45
+ end
46
+
47
+ # Lists the IDs of the Wallets belonging to the User.
48
+ # @return [Array<String>] the IDs of the Wallets belonging to the User
49
+ def list_wallet_ids
50
+ wallets = wallets_api.list_wallets
51
+ wallets.data.map(&:id)
52
+ end
53
+
54
+ private
55
+
56
+ def addresses_api
57
+ @addresses_api ||= Coinbase::Client::AddressesApi.new(Coinbase.configuration.api_client)
58
+ end
59
+
60
+ def wallets_api
61
+ @wallets_api ||= Coinbase::Client::WalletsApi.new(Coinbase.configuration.api_client)
62
+ end
63
+ end
64
+ end