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
@@ -0,0 +1,125 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'constants'
4
+ require 'bigdecimal'
5
+ require 'eth'
6
+ require 'json'
7
+
8
+ module Coinbase
9
+ # A representation of an onchain Transaction.
10
+ # Transactions should be constructed via higher level abstractions like Trade or Transfer.
11
+ class Transaction
12
+ # A representation of a Transaction status.
13
+ module Status
14
+ # The Transaction is awaiting being broadcast to the Network.
15
+ # At this point, transaction hashes may not yet be assigned.
16
+ PENDING = 'pending'
17
+
18
+ # The Transaction has been broadcast to the Network.
19
+ # At this point, at least the transaction hash should be assigned.
20
+ BROADCAST = 'broadcast'
21
+
22
+ # The Transaction is complete and has confirmed on the Network.
23
+ COMPLETE = 'complete'
24
+
25
+ # The Transaction has failed for some reason.
26
+ FAILED = 'failed'
27
+
28
+ # The states that are considered terminal on-chain.
29
+ TERMINAL_STATES = [COMPLETE, FAILED].freeze
30
+ end
31
+
32
+ # Returns a new Transaction object. Do not use this method directly.
33
+ # @param model [Coinbase::Client::Transaction] The underlying Transaction object
34
+ def initialize(model)
35
+ raise unless model.is_a?(Coinbase::Client::Transaction)
36
+
37
+ @model = model
38
+ end
39
+
40
+ # Returns the Unsigned Payload of the Transaction.
41
+ # @return [String] The Unsigned Payload
42
+ def unsigned_payload
43
+ @model.unsigned_payload
44
+ end
45
+
46
+ # Returns the Signed Payload of the Transaction.
47
+ # @return [String] The Signed Payload
48
+ def signed_payload
49
+ @model.signed_payload
50
+ end
51
+
52
+ # Returns the Transaction Hash of the Transaction.
53
+ # @return [String] The Transaction Hash
54
+ def transaction_hash
55
+ @model.transaction_hash
56
+ end
57
+
58
+ # Returns the status of the Transaction.
59
+ # @return [Symbol] The status
60
+ def status
61
+ @model.status
62
+ end
63
+
64
+ # Returns the from address for the Transaction.
65
+ # @return [String] The from address
66
+ def from_address_id
67
+ @model.from_address_id
68
+ end
69
+
70
+ # Returns whether the Transaction is in a terminal state.
71
+ # @return [Boolean] Whether the Transaction is in a terminal state
72
+ def terminal_state?
73
+ Status::TERMINAL_STATES.include?(status)
74
+ end
75
+
76
+ # Returns the link to the transaction on the blockchain explorer.
77
+ # @return [String] The link to the transaction on the blockchain explorer
78
+ def transaction_link
79
+ @model.transaction_link
80
+ end
81
+
82
+ # Returns the underlying raw transaction.
83
+ # @return [Eth::Tx::Eip1559] The raw transaction
84
+ def raw
85
+ return @raw unless @raw.nil?
86
+
87
+ raw_payload = [unsigned_payload].pack('H*')
88
+ parsed_payload = JSON.parse(raw_payload)
89
+
90
+ params = {
91
+ chain_id: parsed_payload['chainId'].to_i(16),
92
+ nonce: parsed_payload['nonce'].to_i(16),
93
+ priority_fee: parsed_payload['maxPriorityFeePerGas'].to_i(16),
94
+ max_gas_fee: parsed_payload['maxFeePerGas'].to_i(16),
95
+ gas_limit: parsed_payload['gas'].to_i(16), # TODO: Handle multiple currencies.
96
+ from: Eth::Address.new(from_address_id),
97
+ to: Eth::Address.new(parsed_payload['to']),
98
+ value: parsed_payload['value'].to_i(16),
99
+ data: parsed_payload['input'] || ''
100
+ }
101
+
102
+ @raw = Eth::Tx::Eip1559.new(Eth::Tx.validate_eip1559_params(params))
103
+ end
104
+
105
+ # Signs the Transaction with the provided key and returns the hex signing payload.
106
+ # @return [String] The hex-encoded signed payload
107
+ def sign(key)
108
+ raw.sign(key)
109
+
110
+ raw.hex
111
+ end
112
+
113
+ # Returns a String representation of the Transaction.
114
+ # @return [String] a String representation of the Transaction
115
+ def to_s
116
+ "Coinbase::Transaction{transaction_hash: '#{transaction_hash}', status: '#{status}'}"
117
+ end
118
+
119
+ # Same as to_s.
120
+ # @return [String] a String representation of the Transaction
121
+ def inspect
122
+ to_s
123
+ end
124
+ end
125
+ end
@@ -11,27 +11,12 @@ module Coinbase
11
11
  # in the native Asset of the Network. Transfers should be created through Wallet#transfer or
12
12
  # Address#transfer.
13
13
  class Transfer
14
- # A representation of a Transfer status.
15
- module Status
16
- # The Transfer is awaiting being broadcast to the Network. At this point, transaction
17
- # hashes may not yet be assigned.
18
- PENDING = :pending
19
-
20
- # The Transfer has been broadcast to the Network. At this point, at least the transaction hash
21
- # should be assigned.
22
- BROADCAST = :broadcast
23
-
24
- # The Transfer is complete, and has confirmed on the Network.
25
- COMPLETE = :complete
26
-
27
- # The Transfer has failed for some reason.
28
- FAILED = :failed
29
- end
30
-
31
14
  # Returns a new Transfer object. Do not use this method directly. Instead, use Wallet#transfer or
32
15
  # Address#transfer.
33
16
  # @param model [Coinbase::Client::Transfer] The underlying Transfer object
34
17
  def initialize(model)
18
+ raise unless model.is_a?(Coinbase::Client::Transfer)
19
+
35
20
  @model = model
36
21
  end
37
22
 
@@ -65,6 +50,10 @@ module Coinbase
65
50
  @model.destination
66
51
  end
67
52
 
53
+ def asset
54
+ @asset ||= Coinbase::Asset.from_model(@model.asset)
55
+ end
56
+
68
57
  # Returns the Asset ID of the Transfer.
69
58
  # @return [Symbol] The Asset ID
70
59
  def asset_id
@@ -74,12 +63,7 @@ module Coinbase
74
63
  # Returns the amount of the asset for the Transfer.
75
64
  # @return [BigDecimal] The amount of the asset
76
65
  def amount
77
- case asset_id
78
- when :eth
79
- BigDecimal(@model.amount) / BigDecimal(Coinbase::WEI_PER_ETHER.to_s)
80
- else
81
- BigDecimal(@model.amount)
82
- end
66
+ BigDecimal(@model.amount) / BigDecimal(10).power(@model.asset.decimals)
83
67
  end
84
68
 
85
69
  # Returns the link to the transaction on the blockchain explorer.
@@ -101,40 +85,22 @@ module Coinbase
101
85
  @model.signed_payload
102
86
  end
103
87
 
88
+ # Returns the Transfer transaction.
89
+ # @return [Coinbase::Transaction] The Transfer transaction
90
+ def transaction
91
+ @transaction ||= Coinbase::Transaction.new(@model.transaction)
92
+ end
93
+
104
94
  # Returns the Transaction Hash of the Transfer.
105
95
  # @return [String] The Transaction Hash
106
96
  def transaction_hash
107
97
  @model.transaction_hash
108
98
  end
109
99
 
110
- # Returns the underlying Transfer transaction, creating it if it has not been yet.
111
- # @return [Eth::Tx::Eip1559] The Transfer transaction
112
- def transaction
113
- return @transaction unless @transaction.nil?
114
-
115
- raw_payload = [unsigned_payload].pack('H*')
116
- parsed_payload = JSON.parse(raw_payload)
117
-
118
- params = {
119
- chain_id: parsed_payload['chainId'].to_i(16),
120
- nonce: parsed_payload['nonce'].to_i(16),
121
- priority_fee: parsed_payload['maxPriorityFeePerGas'].to_i(16),
122
- max_gas_fee: parsed_payload['maxFeePerGas'].to_i(16),
123
- gas_limit: parsed_payload['gas'].to_i(16), # TODO: Handle multiple currencies.
124
- from: Eth::Address.new(from_address_id),
125
- to: Eth::Address.new(parsed_payload['to']),
126
- value: parsed_payload['value'].to_i(16),
127
- data: parsed_payload['input'] || ''
128
- }
129
-
130
- @transaction = Eth::Tx::Eip1559.new(Eth::Tx.validate_eip1559_params(params))
131
- @transaction
132
- end
133
-
134
100
  # Returns the status of the Transfer.
135
101
  # @return [Symbol] The status
136
102
  def status
137
- @model.status
103
+ transaction.status
138
104
  end
139
105
 
140
106
  # Reload reloads the Transfer model with the latest version from the server side.
@@ -144,6 +110,9 @@ module Coinbase
144
110
  transfers_api.get_transfer(wallet_id, from_address_id, id)
145
111
  end
146
112
 
113
+ # Update memoized transaction.
114
+ @transaction = Coinbase::Transaction.new(@model.transaction)
115
+
147
116
  self
148
117
  end
149
118
 
@@ -158,7 +127,7 @@ module Coinbase
158
127
  loop do
159
128
  reload
160
129
 
161
- return self if terminal_state?
130
+ return self if transaction.terminal_state?
162
131
 
163
132
  raise Timeout::Error, 'Transfer timed out' if Time.now - start_time > timeout_seconds
164
133
 
@@ -173,8 +142,8 @@ module Coinbase
173
142
  def to_s
174
143
  "Coinbase::Transfer{transfer_id: '#{id}', network_id: '#{network_id}', " \
175
144
  "from_address_id: '#{from_address_id}', destination_address_id: '#{destination_address_id}', " \
176
- "asset_id: '#{asset_id}', amount: '#{amount}', transaction_hash: '#{transaction_hash}', " \
177
- "transaction_link: '#{transaction_link}', status: '#{status}'}"
145
+ "asset_id: '#{asset_id}', amount: '#{amount}', transaction_link: '#{transaction_link}', " \
146
+ "status: '#{status}'}"
178
147
  end
179
148
 
180
149
  # Same as to_s.
@@ -183,12 +152,10 @@ module Coinbase
183
152
  to_s
184
153
  end
185
154
 
155
+ private
156
+
186
157
  def transfers_api
187
158
  @transfers_api ||= Coinbase::Client::TransfersApi.new(Coinbase.configuration.api_client)
188
159
  end
189
-
190
- def terminal_state?
191
- status == Status::COMPLETE.to_s || status == Status::FAILED.to_s
192
- end
193
160
  end
194
161
  end
@@ -240,11 +240,22 @@ module Coinbase
240
240
  # @param asset_id [Symbol] The ID of the Asset to send
241
241
  # @param destination [Wallet | Address | String] The destination of the transfer. If a Wallet, sends to the Wallet's
242
242
  # default address. If a String, interprets it as the address ID.
243
- # @return [Transfer] The hash of the Transfer transaction.
243
+ # @return [Coinbase::Transfer] The Transfer object.
244
244
  def transfer(amount, asset_id, destination)
245
245
  default_address.transfer(amount, asset_id, destination)
246
246
  end
247
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
+
248
259
  # Exports the Wallet's data to a Data object.
249
260
  # @return [Data] The Wallet data
250
261
  def export
@@ -410,9 +421,9 @@ module Coinbase
410
421
  end
411
422
 
412
423
  def address_path_prefix
413
- # TODO: Add support for other networks.
424
+ # TODO: Push this logic to the backend.
414
425
  @address_path_prefix ||= case network_id.to_s.split('_').first
415
- when 'base'
426
+ when 'base', 'ethereum'
416
427
  "m/44'/60'/0'/0"
417
428
  else
418
429
  raise ArgumentError, "Unsupported network ID: #{network_id}"
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.
@@ -52,13 +55,10 @@ module Coinbase
52
55
 
53
56
  # Configuration object for the Coinbase SDK.
54
57
  class Configuration
55
- attr_reader :base_sepolia_rpc_url, :base_sepolia_client
56
58
  attr_accessor :api_url, :api_key_name, :api_key_private_key, :debug_api, :use_server_signer
57
59
 
58
60
  # Initializes the configuration object.
59
61
  def initialize
60
- @base_sepolia_rpc_url = 'https://sepolia.base.org'
61
- @base_sepolia_client = Jimson::Client.new(@base_sepolia_rpc_url)
62
62
  @api_url = 'https://api.cdp.coinbase.com'
63
63
  @debug_api = false
64
64
  @use_server_signer = false
@@ -79,13 +79,6 @@ module Coinbase
79
79
  @api_key_private_key = data['privateKey']
80
80
  end
81
81
 
82
- # Sets the Base Sepolia RPC URL.
83
- # @param new_base_sepolia_rpc_url [String] the new Base Sepolia RPC URL
84
- def base_sepolia_rpc_url=(new_base_sepolia_rpc_url)
85
- @base_sepolia_rpc_url = new_base_sepolia_rpc_url
86
- @base_sepolia_client = Jimson::Client.new(@base_sepolia_rpc_url)
87
- end
88
-
89
82
  # Returns the API client.
90
83
  # @return [Coinbase::Client::ApiClient] the API client
91
84
  def api_client
@@ -106,6 +99,13 @@ module Coinbase
106
99
  value.to_s.gsub('-', '_').to_sym
107
100
  end
108
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
+
109
109
  # Loads the default user.
110
110
  # @return [Coinbase::User] the default user
111
111
  def self.load_default_user
@@ -119,7 +119,7 @@ module Coinbase
119
119
  def self.call_api
120
120
  yield
121
121
  rescue Coinbase::Client::ApiError => e
122
- raise Coinbase::APIError.from_error(e)
122
+ raise Coinbase::APIError.from_error(e), cause: nil
123
123
  rescue StandardError => e
124
124
  raise e
125
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.6
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-03 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,8 +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
255
+ - lib/coinbase/client/api/stake_api.rb
252
256
  - lib/coinbase/client/api/trades_api.rb
257
+ - lib/coinbase/client/api/transfer_api.rb
253
258
  - lib/coinbase/client/api/transfers_api.rb
254
259
  - lib/coinbase/client/api/users_api.rb
255
260
  - lib/coinbase/client/api/wallets_api.rb
@@ -263,6 +268,7 @@ files:
263
268
  - lib/coinbase/client/models/balance.rb
264
269
  - lib/coinbase/client/models/broadcast_trade_request.rb
265
270
  - lib/coinbase/client/models/broadcast_transfer_request.rb
271
+ - lib/coinbase/client/models/build_staking_operation_request.rb
266
272
  - lib/coinbase/client/models/create_address_request.rb
267
273
  - lib/coinbase/client/models/create_server_signer_request.rb
268
274
  - lib/coinbase/client/models/create_trade_request.rb
@@ -271,14 +277,25 @@ files:
271
277
  - lib/coinbase/client/models/create_wallet_request_wallet.rb
272
278
  - lib/coinbase/client/models/error.rb
273
279
  - lib/coinbase/client/models/faucet_transaction.rb
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
285
+ - lib/coinbase/client/models/request_faucet_funds200_response.rb
274
286
  - lib/coinbase/client/models/seed_creation_event.rb
275
287
  - lib/coinbase/client/models/seed_creation_event_result.rb
276
288
  - lib/coinbase/client/models/server_signer.rb
277
289
  - lib/coinbase/client/models/server_signer_event.rb
278
290
  - lib/coinbase/client/models/server_signer_event_event.rb
279
291
  - lib/coinbase/client/models/server_signer_event_list.rb
292
+ - lib/coinbase/client/models/server_signer_list.rb
280
293
  - lib/coinbase/client/models/signature_creation_event.rb
281
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
297
+ - lib/coinbase/client/models/staking_operation.rb
298
+ - lib/coinbase/client/models/staking_reward.rb
282
299
  - lib/coinbase/client/models/trade.rb
283
300
  - lib/coinbase/client/models/trade_list.rb
284
301
  - lib/coinbase/client/models/transaction.rb
@@ -294,6 +311,9 @@ files:
294
311
  - lib/coinbase/faucet_transaction.rb
295
312
  - lib/coinbase/middleware.rb
296
313
  - lib/coinbase/network.rb
314
+ - lib/coinbase/server_signer.rb
315
+ - lib/coinbase/trade.rb
316
+ - lib/coinbase/transaction.rb
297
317
  - lib/coinbase/transfer.rb
298
318
  - lib/coinbase/user.rb
299
319
  - lib/coinbase/wallet.rb