coinbase-sdk 0.0.6 → 0.0.8

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