coinbase-sdk 0.0.16 → 0.1.0

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 (119) hide show
  1. checksums.yaml +4 -4
  2. data/lib/coinbase/address/wallet_address.rb +24 -17
  3. data/lib/coinbase/address.rb +17 -19
  4. data/lib/coinbase/asset.rb +11 -8
  5. data/lib/coinbase/client/api/addresses_api.rb +1 -1
  6. data/lib/coinbase/client/api/assets_api.rb +1 -1
  7. data/lib/coinbase/client/api/contract_events_api.rb +18 -10
  8. data/lib/coinbase/client/api/external_addresses_api.rb +1 -1
  9. data/lib/coinbase/client/api/networks_api.rb +1 -1
  10. data/lib/coinbase/client/api/server_signers_api.rb +1 -1
  11. data/lib/coinbase/client/api/stake_api.rb +1 -242
  12. data/lib/coinbase/client/api/trades_api.rb +1 -1
  13. data/lib/coinbase/client/api/transfers_api.rb +1 -1
  14. data/lib/coinbase/client/api/users_api.rb +1 -1
  15. data/lib/coinbase/client/api/validators_api.rb +3 -3
  16. data/lib/coinbase/client/api/wallet_stake_api.rb +263 -0
  17. data/lib/coinbase/client/api/wallets_api.rb +1 -1
  18. data/lib/coinbase/client/api/webhooks_api.rb +1 -1
  19. data/lib/coinbase/client/api_client.rb +1 -1
  20. data/lib/coinbase/client/api_error.rb +1 -1
  21. data/lib/coinbase/client/configuration.rb +11 -1
  22. data/lib/coinbase/client/models/address.rb +22 -5
  23. data/lib/coinbase/client/models/address_balance_list.rb +1 -1
  24. data/lib/coinbase/client/models/address_historical_balance_list.rb +1 -1
  25. data/lib/coinbase/client/models/address_list.rb +1 -1
  26. data/lib/coinbase/client/models/asset.rb +1 -1
  27. data/lib/coinbase/client/models/balance.rb +1 -1
  28. data/lib/coinbase/client/models/broadcast_staking_operation_request.rb +1 -1
  29. data/lib/coinbase/client/models/broadcast_trade_request.rb +1 -1
  30. data/lib/coinbase/client/models/broadcast_transfer_request.rb +1 -1
  31. data/lib/coinbase/client/models/build_staking_operation_request.rb +1 -1
  32. data/lib/coinbase/client/models/contract_event.rb +100 -9
  33. data/lib/coinbase/client/models/contract_event_list.rb +1 -1
  34. data/lib/coinbase/client/models/create_address_request.rb +15 -5
  35. data/lib/coinbase/client/models/create_server_signer_request.rb +1 -1
  36. data/lib/coinbase/client/models/create_staking_operation_request.rb +1 -1
  37. data/lib/coinbase/client/models/create_trade_request.rb +1 -1
  38. data/lib/coinbase/client/models/create_transfer_request.rb +1 -1
  39. data/lib/coinbase/client/models/create_wallet_request.rb +1 -1
  40. data/lib/coinbase/client/models/create_wallet_request_wallet.rb +1 -1
  41. data/lib/coinbase/client/models/create_webhook_request.rb +1 -1
  42. data/lib/coinbase/client/models/error.rb +1 -1
  43. data/lib/coinbase/client/models/ethereum_validator_metadata.rb +12 -12
  44. data/lib/coinbase/client/models/faucet_transaction.rb +1 -1
  45. data/lib/coinbase/client/models/feature.rb +3 -2
  46. data/lib/coinbase/client/models/feature_set.rb +1 -1
  47. data/lib/coinbase/client/models/fetch_historical_staking_balances200_response.rb +1 -1
  48. data/lib/coinbase/client/models/fetch_staking_rewards200_response.rb +1 -1
  49. data/lib/coinbase/client/models/fetch_staking_rewards_request.rb +1 -1
  50. data/lib/coinbase/client/models/get_staking_context_request.rb +1 -1
  51. data/lib/coinbase/client/models/historical_balance.rb +1 -1
  52. data/lib/coinbase/client/models/network.rb +15 -5
  53. data/lib/coinbase/client/models/network_identifier.rb +1 -1
  54. data/lib/coinbase/client/models/seed_creation_event.rb +1 -1
  55. data/lib/coinbase/client/models/seed_creation_event_result.rb +1 -1
  56. data/lib/coinbase/client/models/server_signer.rb +1 -1
  57. data/lib/coinbase/client/models/server_signer_event.rb +1 -1
  58. data/lib/coinbase/client/models/server_signer_event_event.rb +1 -1
  59. data/lib/coinbase/client/models/server_signer_event_list.rb +1 -1
  60. data/lib/coinbase/client/models/server_signer_list.rb +1 -1
  61. data/lib/coinbase/client/models/signature_creation_event.rb +1 -1
  62. data/lib/coinbase/client/models/signature_creation_event_result.rb +1 -1
  63. data/lib/coinbase/client/models/signed_voluntary_exit_message_metadata.rb +1 -1
  64. data/lib/coinbase/client/models/sponsored_send.rb +1 -1
  65. data/lib/coinbase/client/models/staking_balance.rb +1 -1
  66. data/lib/coinbase/client/models/staking_context.rb +1 -1
  67. data/lib/coinbase/client/models/staking_context_context.rb +1 -1
  68. data/lib/coinbase/client/models/staking_operation.rb +3 -3
  69. data/lib/coinbase/client/models/staking_operation_metadata.rb +1 -1
  70. data/lib/coinbase/client/models/staking_reward.rb +1 -1
  71. data/lib/coinbase/client/models/staking_reward_format.rb +1 -1
  72. data/lib/coinbase/client/models/staking_reward_usd_value.rb +1 -1
  73. data/lib/coinbase/client/models/trade.rb +1 -1
  74. data/lib/coinbase/client/models/trade_list.rb +1 -1
  75. data/lib/coinbase/client/models/transaction.rb +16 -6
  76. data/lib/coinbase/client/models/transaction_type.rb +1 -1
  77. data/lib/coinbase/client/models/transfer.rb +1 -1
  78. data/lib/coinbase/client/models/transfer_list.rb +1 -1
  79. data/lib/coinbase/client/models/update_webhook_request.rb +1 -1
  80. data/lib/coinbase/client/models/user.rb +1 -1
  81. data/lib/coinbase/client/models/validator.rb +24 -3
  82. data/lib/coinbase/client/models/validator_details.rb +1 -1
  83. data/lib/coinbase/client/models/validator_list.rb +1 -1
  84. data/lib/coinbase/client/models/validator_status.rb +52 -0
  85. data/lib/coinbase/client/models/wallet.rb +1 -1
  86. data/lib/coinbase/client/models/wallet_list.rb +1 -1
  87. data/lib/coinbase/client/models/webhook.rb +1 -1
  88. data/lib/coinbase/client/models/webhook_event_filter.rb +1 -1
  89. data/lib/coinbase/client/models/webhook_event_type.rb +1 -1
  90. data/lib/coinbase/client/models/webhook_list.rb +1 -1
  91. data/lib/coinbase/client/version.rb +1 -1
  92. data/lib/coinbase/client.rb +3 -1
  93. data/lib/coinbase/constants.rb +0 -10
  94. data/lib/coinbase/contract_event.rb +104 -0
  95. data/lib/coinbase/correlation.rb +30 -0
  96. data/lib/coinbase/destination.rb +11 -9
  97. data/lib/coinbase/errors.rb +7 -0
  98. data/lib/coinbase/middleware.rb +2 -0
  99. data/lib/coinbase/network.rb +103 -20
  100. data/lib/coinbase/smart_contract.rb +106 -0
  101. data/lib/coinbase/staking_balance.rb +11 -5
  102. data/lib/coinbase/staking_operation.rb +134 -36
  103. data/lib/coinbase/staking_reward.rb +1 -1
  104. data/lib/coinbase/trade.rb +10 -9
  105. data/lib/coinbase/transaction.rb +6 -0
  106. data/lib/coinbase/transfer.rb +11 -10
  107. data/lib/coinbase/validator.rb +18 -10
  108. data/lib/coinbase/version.rb +5 -0
  109. data/lib/coinbase/wallet.rb +137 -145
  110. data/lib/coinbase/webhook.rb +181 -0
  111. data/lib/coinbase.rb +50 -19
  112. metadata +9 -9
  113. data/lib/coinbase/client/models/ethereum_validator.rb +0 -374
  114. data/lib/coinbase/client/models/get_validator200_response.rb +0 -221
  115. data/lib/coinbase/client/models/get_validator200_response_validator.rb +0 -214
  116. data/lib/coinbase/client/models/native_eth_staking_context.rb +0 -254
  117. data/lib/coinbase/client/models/partial_eth_staking_context.rb +0 -254
  118. data/lib/coinbase/client/models/validator_list_data.rb +0 -216
  119. data/lib/coinbase/user.rb +0 -65
@@ -12,6 +12,8 @@ module Coinbase
12
12
  # each of which can hold a balance of one or more Assets. Wallets can create new Addresses, list their addresses,
13
13
  # list their balances, and transfer Assets to other Addresses.
14
14
  class Wallet
15
+ extend Forwardable
16
+
15
17
  # The maximum number of addresses in a Wallet.
16
18
  MAX_ADDRESSES = 20
17
19
 
@@ -54,18 +56,19 @@ module Coinbase
54
56
  end
55
57
 
56
58
  # Creates a new Wallet on the specified Network and generate a default address for it.
57
- # @param network_id [String] (Optional) the ID of the blockchain network. Defaults to 'base-sepolia'.
59
+ # @param network [Coinbase::Network, Symbol] (Optional) The network object or ID to create the
60
+ # Wallet on. When omitted this uses the SDK configured default network.
58
61
  # @param interval_seconds [Integer] The interval at which to poll the CDPService for the Wallet to
59
62
  # have an active seed, if using a ServerSigner, in seconds
60
63
  # @param timeout_seconds [Integer] The maximum amount of time to wait for the ServerSigner to
61
64
  # create a seed for the Wallet, in seconds
62
65
  # @return [Coinbase::Wallet] the new Wallet
63
- def create(network_id: 'base-sepolia', interval_seconds: 0.2, timeout_seconds: 20)
66
+ def create(network: Coinbase.default_network, interval_seconds: 0.2, timeout_seconds: 20)
64
67
  model = Coinbase.call_api do
65
68
  wallets_api.create_wallet(
66
69
  create_wallet_request: {
67
70
  wallet: {
68
- network_id: Coinbase.normalize_network(network_id),
71
+ network_id: Coinbase.normalize_network(network),
69
72
  use_server_signer: Coinbase.use_server_signer?
70
73
  }
71
74
  }
@@ -123,8 +126,7 @@ module Coinbase
123
126
  end
124
127
  end
125
128
 
126
- # Returns a new Wallet object. Do not use this method directly. Instead, use User#create_wallet or
127
- # User#import_wallet.
129
+ # Returns a new Wallet object. Do not use this method directly. Instead use Coinbase::Wallet.create.
128
130
  # @param model [Coinbase::Client::Wallet] The underlying Wallet object
129
131
  # @param seed [String] (Optional) The seed to use for the Wallet. Expects a 32-byte hexadecimal with no 0x prefix.
130
132
  # If nil, a new seed will be generated. If the empty string, no seed is generated, and the Wallet will be
@@ -140,19 +142,98 @@ module Coinbase
140
142
  @master = master_node(seed)
141
143
  end
142
144
 
145
+ # @!method transfer
146
+ # Transfers the amount of the Asset from the default address to the specified destination.
147
+ # @param amount [Integer, Float, BigDecimal] The amount of the Asset to send
148
+ # @param asset_id [Symbol] The ID of the Asset to send
149
+ # @param destination [Wallet | Address | String] The destination of the transfer.
150
+ # If a Wallet, sends to the Wallet's default address.
151
+ # If a String, interprets it as the address ID.
152
+ # @param gasless [Boolean] Whether the transfer should be gasless. Defaults to false.
153
+ # @return [Coinbase::Transfer] The Transfer object.
154
+ # (see Coinbase::Address::WalletAddress#transfer)
155
+
156
+ # @!method trade
157
+ # Trades the specified amount from one asset to another using the default address.
158
+ # @param amount [Integer, Float, BigDecimal] The amount of the Asset to send.
159
+ # @param from_asset_id [Symbol] The ID of the Asset to trade from.
160
+ # @param to_asset_id [Symbol] The ID of the Asset to trade to.
161
+ # default address. If a String, interprets it as the address ID.
162
+ # @return [Coinbase::Trade] The Trade object.
163
+
164
+ # @!method faucet
165
+ # Requests funds from the faucet for the Wallet's default address and returns the faucet transaction.
166
+ # This is only supported on testnet networks.
167
+ # @return [Coinbase::FaucetTransaction] The successful faucet transaction
168
+ # @raise [Coinbase::FaucetLimitReachedError] If the faucet limit has been reached for the address or user.
169
+ # @raise [Coinbase::Client::ApiError] If an unexpected error occurs while requesting faucet funds.
170
+
171
+ # @!method stake
172
+ # Stakes the given amount of the given Asset for the default address.
173
+ # @param amount [Integer, Float, BigDecimal] The amount of the Asset to stake.
174
+ # @param asset_id [Symbol] The ID of the Asset to stake.
175
+ # @param mode [Symbol] (Optional) The staking mode. Defaults to :default.
176
+ # @param options [Hash] (Optional) Additional options for the staking operation.
177
+ # @return [Coinbase::StakingOperation] The stake operation
178
+
179
+ # @!method unstake
180
+ # Unstakes the given amount of the given Asset on the default address.
181
+ # @param amount [Integer, Float, BigDecimal] The amount of the Asset to unstake.
182
+ # @param asset_id [Symbol] The ID of the Asset to unstake.
183
+ # @param mode [Symbol] (Optional) The staking mode. Defaults to :default.
184
+ # @param options [Hash] (Optional) Additional options for the unstaking operation.
185
+ # @return [Coinbase::StakingOperation] The unstake operation
186
+
187
+ # @!method claim_stake
188
+ # Claims stake of the given amount of the given Asset for the default address.
189
+ # @param amount [Integer, Float, BigDecimal] The amount of the Asset to claim_stake.
190
+ # @param asset_id [Symbol] The ID of the Asset to claim_stake.
191
+ # @param mode [Symbol] (Optional) The staking mode. Defaults to :default.
192
+ # @param options [Hash] (Optional) Additional options for the unstaking operation.
193
+ # @return [Coinbase::StakingOperation] The claim_stake operation
194
+
195
+ # @!method staking_balances
196
+ # Retrieves the balances used for staking for the supplied asset for the default address.
197
+ # @param asset_id [Symbol] The asset to retrieve staking balances for
198
+ # @param mode [Symbol] The staking mode. Defaults to :default.
199
+ # @param options [Hash] Additional options for the staking operation
200
+ # @return [Hash] The staking balances
201
+ # @return [BigDecimal] :stakeable_balance The amount of the asset that can be staked
202
+ # @return [BigDecimal] :unstakeable_balance The amount of the asset that is currently staked and cannot be unstaked
203
+ # @return [BigDecimal] :claimable_balance The amount of the asset that can be claimed
204
+
205
+ # @!method stakeable_balance
206
+ # Retrieves the stakeable balance of the supplied asset for the default address.
207
+ # @param asset_id [Symbol] The asset to retrieve the stakeable balance for
208
+ # @param mode [Symbol] The staking mode. Defaults to :default.
209
+ # @param options [Hash] Additional options for the staking operation
210
+ # @return [BigDecimal] The stakeable balance
211
+
212
+ # @!method unstakeable_balance
213
+ # Retrieves the unstakeable balance for the supplied asset.
214
+ # Currently only the default_address is used to source the unstakeable balance.
215
+ # @param asset_id [Symbol] The asset to retrieve the unstakeable balance for
216
+ # @param mode [Symbol] The staking mode. Defaults to :default.
217
+ # @param options [Hash] Additional options for the staking operation
218
+ # @return [BigDecimal] The unstakeable balance
219
+
220
+ # @!method claimable_balance
221
+ # Retrieves the claimable balance for the supplied asset.
222
+ # Currently only the default_address is used to source the claimable balance.
223
+ # @param asset_id [Symbol] The asset to retrieve the claimable balance for
224
+ # @param mode [Symbol] The staking mode. Defaults to :default.
225
+ # @param options [Hash] Additional options for the staking operation
226
+ # @return [BigDecimal] The claimable balance
227
+
228
+ def_delegators :default_address, :transfer, :trade, :faucet, :stake, :unstake, :claim_stake, :staking_balances,
229
+ :stakeable_balance, :unstakeable_balance, :claimable_balance
230
+
143
231
  # Returns the addresses belonging to the Wallet.
144
232
  # @return [Array<Coinbase::WalletAddress>] The addresses belonging to the Wallet
145
233
  def addresses
146
- @addresses ||= begin
147
- address_list = Coinbase.call_api do
148
- addresses_api.list_addresses(@model.id, { limit: MAX_ADDRESSES })
149
- end
234
+ return @addresses unless @addresses.nil?
150
235
 
151
- # Build the WalletAddress objects, injecting the key if available.
152
- address_list.data.each_with_index.map do |address_model, index|
153
- build_wallet_address(address_model, index)
154
- end
155
- end
236
+ set_addresses
156
237
  end
157
238
 
158
239
  # Returns the Wallet ID.
@@ -161,10 +242,10 @@ module Coinbase
161
242
  @model.id
162
243
  end
163
244
 
164
- # Returns the Network ID of the Wallet.
165
- # @return [Symbol] The Network ID
166
- def network_id
167
- Coinbase.to_sym(@model.network_id)
245
+ # Returns the Network of the Wallet.
246
+ # @return [Coinbase::Network] The Network of the Wallet
247
+ def network
248
+ @network ||= Coinbase::Network.from_id(@model.network_id)
168
249
  end
169
250
 
170
251
  # Returns the ServerSigner Status of the Wallet.
@@ -198,7 +279,12 @@ module Coinbase
198
279
  # Creates a new Address in the Wallet.
199
280
  # @return [Address] The new Address
200
281
  def create_address
201
- opts = { create_address_request: {} }
282
+ req = {}
283
+
284
+ # Ensure that the address cache is set before creating a new address.
285
+ # This ensures that for a server signer, the addresses have been loaded and we
286
+ # can create a new address and add it to a cache.
287
+ set_addresses if @addresses.nil?
202
288
 
203
289
  unless Coinbase.use_server_signer?
204
290
  # The index for the next address is the number of addresses already registered.
@@ -206,22 +292,25 @@ module Coinbase
206
292
 
207
293
  key = derive_key(private_key_index)
208
294
 
209
- opts = {
210
- create_address_request: {
211
- public_key: key.public_key.compressed.unpack1('H*'),
212
- attestation: create_attestation(key)
213
- }
295
+ req = {
296
+ public_key: key.public_key.compressed.unpack1('H*'),
297
+ attestation: create_attestation(key),
298
+ address_index: private_key_index
214
299
  }
215
300
  end
216
301
 
217
302
  address_model = Coinbase.call_api do
218
- addresses_api.create_address(id, opts)
303
+ addresses_api.create_address(id, { create_address_request: req })
219
304
  end
220
305
 
221
- # Auto-reload wallet to set default address on first address creation.
306
+ # Default address can be nil because either this is the first address being
307
+ # created for this wallet or the addresses cache has not yet been loaded.
308
+
309
+ # If the default address is nil, we must reload the wallet model after creating
310
+ # the address, in order for the default address to be set.
222
311
  reload if default_address.nil?
223
312
 
224
- # Cache the address in our memoized list
313
+ # The addreses cache is already created, so we can add the new address to the cache.
225
314
  address = WalletAddress.new(address_model, key)
226
315
  @addresses << address
227
316
  address
@@ -263,110 +352,6 @@ module Coinbase
263
352
  Coinbase::Balance.from_model_and_asset_id(response, asset_id).amount
264
353
  end
265
354
 
266
- # Transfers the given amount of the given Asset to the specified address or wallet.
267
- # Only same-network Transfers are supported. Currently only the default_address is used to source the Transfer.
268
- # @param amount [Integer, Float, BigDecimal] The amount of the Asset to send
269
- # @param asset_id [Symbol] The ID of the Asset to send
270
- # @param destination [Wallet | Address | String] The destination of the transfer. If a Wallet, sends to the Wallet's
271
- # default address. If a String, interprets it as the address ID.
272
- # @param gasless [Boolean] Whether gas fee for the transfer should be covered by Coinbase.
273
- # Defaults to false. Check the API documentation for network and asset support.
274
- # @return [Coinbase::Transfer] The Transfer object.
275
- def transfer(amount, asset_id, destination, options = {})
276
- # For ruby 2.7 compatibility we cannot pass in keyword args when the create wallet
277
- # options is empty
278
- return default_address.transfer(amount, asset_id, destination) if options.empty?
279
-
280
- default_address.transfer(amount, asset_id, destination, **options)
281
- end
282
-
283
- # Trades the given amount of the given Asset for another Asset.
284
- # Currently only the default_address is used to source the Trade
285
- # @param amount [Integer, Float, BigDecimal] The amount of the Asset to send.
286
- # @param from_asset_id [Symbol] The ID of the Asset to trade from. For Ether, :eth, :gwei, and :wei are supported.
287
- # @param to_asset_id [Symbol] The ID of the Asset to trade to. For Ether, :eth, :gwei, and :wei are supported.
288
- # default address. If a String, interprets it as the address ID.
289
- # @return [Coinbase::Trade] The Trade object.
290
- def trade(amount, from_asset_id, to_asset_id)
291
- default_address.trade(amount, from_asset_id, to_asset_id)
292
- end
293
-
294
- # Stakes the given amount of the given Asset.
295
- # Currently only the default_address is used to source the Stake.
296
- # @param amount [Integer, Float, BigDecimal] The amount of the Asset to stake.
297
- # @param asset_id [Symbol] The ID of the Asset to stake.
298
- # @param mode [Symbol] (Optional) The staking mode. Defaults to :default.
299
- # @param options [Hash] (Optional) Additional options for the staking operation.
300
- # @return [Coinbase::StakingOperation] The stake operation
301
- def stake(amount, asset_id, mode: :default, options: {})
302
- default_address.stake(amount, asset_id, mode: mode, options: options)
303
- end
304
-
305
- # Unstakes the given amount of the given Asset.
306
- # Currently only the default_address is used to source the Unstake.
307
- # @param amount [Integer, Float, BigDecimal] The amount of the Asset to unstake.
308
- # @param asset_id [Symbol] The ID of the Asset to unstake.
309
- # @param mode [Symbol] (Optional) The staking mode. Defaults to :default.
310
- # @param options [Hash] (Optional) Additional options for the unstaking operation.
311
- # @return [Coinbase::StakingOperation] The unstake operation
312
- def unstake(amount, asset_id, mode: :default, options: {})
313
- default_address.unstake(amount, asset_id, mode: mode, options: options)
314
- end
315
-
316
- # Claims stake of the given amount of the given Asset.
317
- # Currently only the default_address is used as the source for claim_stake.
318
- # @param amount [Integer, Float, BigDecimal] The amount of the Asset to claim_stake.
319
- # @param asset_id [Symbol] The ID of the Asset to claim_stake.
320
- # @param mode [Symbol] (Optional) The staking mode. Defaults to :default.
321
- # @param options [Hash] (Optional) Additional options for the unstaking operation.
322
- # @return [Coinbase::StakingOperation] The claim_stake operation
323
- def claim_stake(amount, asset_id, mode: :default, options: {})
324
- default_address.claim_stake(amount, asset_id, mode: mode, options: options)
325
- end
326
-
327
- # Retrieves the balances used for staking for the supplied asset.
328
- # Currently only the default_address is used to source the staking balances.
329
- # @param asset_id [Symbol] The asset to retrieve staking balances for
330
- # @param mode [Symbol] The staking mode. Defaults to :default.
331
- # @param options [Hash] Additional options for the staking operation
332
- # @return [Hash] The staking balances
333
- # @return [BigDecimal] :stakeable_balance The amount of the asset that can be staked
334
- # @return [BigDecimal] :unstakeable_balance The amount of the asset that is currently staked and cannot be unstaked
335
- # @return [BigDecimal] :claimable_balance The amount of the asset that can be claimed
336
- def staking_balances(asset_id, mode: :default, options: {})
337
- default_address.staking_balances(asset_id, mode: mode, options: options)
338
- end
339
-
340
- # Retrieves the stakeable balance for the supplied asset.
341
- # Currently only the default_address is used to source the stakeable balance.
342
- # @param asset_id [Symbol] The asset to retrieve the stakeable balance for
343
- # @param mode [Symbol] The staking mode. Defaults to :default.
344
- # @param options [Hash] Additional options for the staking operation
345
- # @return [BigDecimal] The stakeable balance
346
- def stakeable_balance(asset_id, mode: :default, options: {})
347
- default_address.stakeable_balance(asset_id, mode: mode, options: options)
348
- end
349
-
350
- # Retrieves the unstakeable balance for the supplied asset.
351
- # Currently only the default_address is used to source the unstakeable balance.
352
- # @param asset_id [Symbol] The asset to retrieve the unstakeable balance for
353
- # @param mode [Symbol] The staking mode. Defaults to :default.
354
- # @param options [Hash] Additional options for the staking operation
355
- # @return [BigDecimal] The unstakeable balance
356
- def unstakeable_balance(asset_id, mode: :default, options: {})
357
- default_address.unstakeable_balance(asset_id, mode: mode, options: options)
358
- end
359
-
360
- # Retrieves the claimable balance for the supplied asset.
361
- # Currently only the default_address is used to source the claimable balance.
362
- # @param asset_id [Symbol] The asset to retrieve the claimable balance for
363
- # @param mode [Symbol] The staking mode. Defaults to :default.
364
- # @param options [Hash] Additional options for the staking operation
365
- # @return [BigDecimal] The claimable balance
366
- def claimable_balance(asset_id, mode: :default, options: {})
367
- default_address.claimable_balance(asset_id, mode: mode, options: options)
368
- end
369
-
370
355
  # Exports the Wallet's data to a Data object.
371
356
  # @return [Coinbase::Wallet::Data] The Wallet data
372
357
  def export
@@ -378,11 +363,6 @@ module Coinbase
378
363
  Data.new(wallet_id: id, seed: @master.seed_hex)
379
364
  end
380
365
 
381
- # Requests funds from the faucet for the Wallet's default address and returns the faucet transaction.
382
- # This is only supported on testnet networks.
383
- # @return [Coinbase::FaucetTransaction] The successful faucet transaction
384
- # @raise [Coinbase::FaucetLimitReachedError] If the faucet limit has been reached for the address or user.
385
- # @raise [Coinbase::Client::ApiError] If an unexpected error occurs while requesting faucet funds.
386
366
  def faucet
387
367
  Coinbase.call_api do
388
368
  Coinbase::FaucetTransaction.new(addresses_api.request_faucet_funds(id, default_address.id))
@@ -477,8 +457,12 @@ module Coinbase
477
457
  # Returns a String representation of the Wallet.
478
458
  # @return [String] a String representation of the Wallet
479
459
  def to_s
480
- "Coinbase::Wallet{wallet_id: '#{id}', network_id: '#{network_id}', " \
481
- "default_address: '#{@model.default_address&.address_id}'}"
460
+ Coinbase.pretty_print_object(
461
+ self.class,
462
+ id: id,
463
+ network_id: network.id,
464
+ default_address: @model.default_address&.address_id
465
+ )
482
466
  end
483
467
 
484
468
  # Same as to_s.
@@ -507,13 +491,11 @@ module Coinbase
507
491
  end
508
492
 
509
493
  def address_path_prefix
510
- # TODO: Push this logic to the backend.
511
- @address_path_prefix ||= case network_id.to_s.split('_').first
512
- when 'base', 'ethereum', 'polygon'
513
- "m/44'/60'/0'/0"
514
- else
515
- raise ArgumentError, "Unsupported network ID: #{network_id}"
516
- end
494
+ if network.address_path_prefix.nil? || network.address_path_prefix.empty?
495
+ raise ArgumentError, "Cannot create address for network #{network.id}"
496
+ end
497
+
498
+ network.address_path_prefix
517
499
  end
518
500
 
519
501
  # Derives a key for the given address index.
@@ -595,5 +577,15 @@ module Coinbase
595
577
  def wallets_api
596
578
  @wallets_api ||= Coinbase::Client::WalletsApi.new(Coinbase.configuration.api_client)
597
579
  end
580
+
581
+ def set_addresses
582
+ address_list = Coinbase.call_api do
583
+ addresses_api.list_addresses(@model.id, { limit: MAX_ADDRESSES })
584
+ end
585
+
586
+ @addresses = address_list.data.each_with_index.map do |address_model, index|
587
+ build_wallet_address(address_model, index)
588
+ end
589
+ end
598
590
  end
599
591
  end
@@ -0,0 +1,181 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Coinbase
4
+ # A representation of a Webhook.
5
+ # This class provides methods to create, list, update, and delete webhooks
6
+ # that are used to receive notifications of specific events.
7
+ class Webhook
8
+ # Event type for ERC20 transfer
9
+ ERC20_TRANSFER_EVENT = 'erc20_transfer'
10
+
11
+ # Event type for ERC721 transfer
12
+ ERC721_TRANSFER_EVENT = 'erc721_transfer'
13
+
14
+ class << self
15
+ # Creates a new webhook for a specified network.
16
+ #
17
+ # @param network_id [String] The network ID for which the webhook is created.
18
+ # @param notification_uri [String] The URI where notifications should be sent.
19
+ # @param event_type [String] The type of event for the webhook. Must be one of the following:
20
+ # - `Coinbase::Webhook::ERC20_TRANSFER_EVENT`
21
+ # - `Coinbase::Webhook::ERC721_TRANSFER_EVENT`
22
+ # @param event_filters [Array<Hash>] Filters applied to the events that determine
23
+ # which specific events trigger the webhook. Each filter should be a hash that
24
+ # can include keys like `contract_address`, `from_address`, or `to_address`.
25
+ # @return [Coinbase::Webhook] A new instance of Webhook.
26
+ #
27
+ # @example Create a new webhook
28
+ # webhook = Coinbase::Webhook.create(
29
+ # network_id: :ethereum_mainnet,
30
+ # notification_uri: 'https://example.com/callback',
31
+ # event_type: 'transaction',
32
+ # event_filters: [{ 'contract_address' => '0x...', 'from_address' => '0x...', 'to_address' => '0x...' }]
33
+ # )
34
+ def create(network_id:, notification_uri:, event_type:, event_filters:)
35
+ model = Coinbase.call_api do
36
+ webhooks_api.create_webhook(
37
+ create_webhook_request: {
38
+ network_id: Coinbase.normalize_network(network_id),
39
+ notification_uri: notification_uri,
40
+ event_type: event_type,
41
+ event_filters: event_filters
42
+ }
43
+ )
44
+ end
45
+
46
+ new(model)
47
+ end
48
+
49
+ # Enumerates the webhooks.
50
+ # The result is an enumerator that lazily fetches from the server, and can be iterated over,
51
+ # converted to an array, etc...
52
+ # @return [Enumerable<Coinbase::Webhook>] Enumerator that returns webhooks
53
+ def list
54
+ Coinbase::Pagination.enumerate(method(:fetch_webhooks_page).to_proc) do |webhook|
55
+ Coinbase::Webhook.new(webhook)
56
+ end
57
+ end
58
+
59
+ private
60
+
61
+ def webhooks_api
62
+ Coinbase::Client::WebhooksApi.new(Coinbase.configuration.api_client)
63
+ end
64
+
65
+ def fetch_webhooks_page(page)
66
+ webhooks_api.list_webhooks({ limit: DEFAULT_PAGE_LIMIT, page: page })
67
+ end
68
+ end
69
+
70
+ # Initializes a new Webhook object.
71
+ #
72
+ # @param model [Coinbase::Client::Webhook] The underlying Webhook object.
73
+ # @raise [ArgumentError] If the model is not a Coinbase::Client::Webhook.
74
+ def initialize(model)
75
+ raise ArgumentError, 'model must be a Webhook' unless model.is_a?(Coinbase::Client::Webhook)
76
+
77
+ @model = model
78
+ end
79
+
80
+ # Returns the ID of the webhook.
81
+ #
82
+ # @return [String] The ID of the webhook.
83
+ def id
84
+ @model.id
85
+ end
86
+
87
+ # Returns the network ID associated with the webhook.
88
+ #
89
+ # @return [Symbol] The network ID of the webhook.
90
+ def network_id
91
+ Coinbase.to_sym(@model.network_id)
92
+ end
93
+
94
+ # Returns the notification URI of the webhook.
95
+ #
96
+ # @return [String] The URI where notifications are sent.
97
+ def notification_uri
98
+ @model.notification_uri
99
+ end
100
+
101
+ # Returns the event type of the webhook.
102
+ #
103
+ # @return [String] The type of event the webhook listens for.
104
+ def event_type
105
+ @model.event_type
106
+ end
107
+
108
+ # Returns the event filters applied to the webhook.
109
+ #
110
+ # @return [Array<Coinbase::Client::WebhookEventFilter>] An array of event filters used by the webhook.
111
+ def event_filters
112
+ @model.event_filters
113
+ end
114
+
115
+ # Updates the webhook with a new notification URI.
116
+ #
117
+ # @param notification_uri [String] The new URI for webhook notifications.
118
+ # @return [self] Returns the updated Webhook object.
119
+ #
120
+ # @example Update the notification URI of a webhook
121
+ # webhook.update(notification_uri: 'https://new-url.com/callback')
122
+ def update(notification_uri:)
123
+ model = Coinbase.call_api do
124
+ webhooks_api.update_webhook(
125
+ id,
126
+ update_webhook_request: {
127
+ network_id: network_id,
128
+ notification_uri: notification_uri,
129
+ event_type: event_type,
130
+ event_filters: event_filters.map(&:to_hash)
131
+ }
132
+ )
133
+ end
134
+
135
+ @model = model
136
+
137
+ self
138
+ end
139
+
140
+ # Deletes the webhook.
141
+ #
142
+ # @return [self] Returns the Webhook object with nil attributes.
143
+ #
144
+ # @example Delete a webhook
145
+ # webhook.delete
146
+ def delete
147
+ Coinbase.call_api do
148
+ webhooks_api.delete_webhook(id)
149
+ end
150
+
151
+ @model = nil
152
+
153
+ self
154
+ end
155
+
156
+ # Returns a String representation of the Webhook.
157
+ # @return [String] a String representation of the Webhook
158
+ def to_s
159
+ Coinbase.pretty_print_object(
160
+ self.class,
161
+ id: @model.id,
162
+ network_id: @model.network_id,
163
+ event_type: @model.event_type,
164
+ notification_uri: @model.notification_uri,
165
+ event_filters: @model.event_filters.map(&:to_hash).to_json
166
+ )
167
+ end
168
+
169
+ # Same as to_s.
170
+ # @return [String] a String representation of the Webhook
171
+ def inspect
172
+ to_s
173
+ end
174
+
175
+ private
176
+
177
+ def webhooks_api
178
+ @webhooks_api ||= Coinbase::Client::WebhooksApi.new(Coinbase.configuration.api_client)
179
+ end
180
+ end
181
+ end
data/lib/coinbase.rb CHANGED
@@ -5,11 +5,13 @@ require_relative 'coinbase/address/wallet_address'
5
5
  require_relative 'coinbase/address/external_address'
6
6
  require_relative 'coinbase/asset'
7
7
  require_relative 'coinbase/authenticator'
8
+ require_relative 'coinbase/correlation'
8
9
  require_relative 'coinbase/balance'
9
10
  require_relative 'coinbase/balance_map'
10
11
  require_relative 'coinbase/historical_balance'
11
12
  require_relative 'coinbase/client'
12
13
  require_relative 'coinbase/constants'
14
+ require_relative 'coinbase/contract_event'
13
15
  require_relative 'coinbase/destination'
14
16
  require_relative 'coinbase/errors'
15
17
  require_relative 'coinbase/faucet_transaction'
@@ -19,14 +21,16 @@ require_relative 'coinbase/pagination'
19
21
  require_relative 'coinbase/trade'
20
22
  require_relative 'coinbase/transfer'
21
23
  require_relative 'coinbase/transaction'
22
- require_relative 'coinbase/user'
23
24
  require_relative 'coinbase/wallet'
24
25
  require_relative 'coinbase/server_signer'
26
+ require_relative 'coinbase/smart_contract'
25
27
  require_relative 'coinbase/sponsored_send'
26
28
  require_relative 'coinbase/staking_balance'
27
29
  require_relative 'coinbase/staking_operation'
28
30
  require_relative 'coinbase/staking_reward'
29
31
  require_relative 'coinbase/validator'
32
+ require_relative 'coinbase/version'
33
+ require_relative 'coinbase/webhook'
30
34
  require 'json'
31
35
 
32
36
  # The Coinbase SDK.
@@ -73,6 +77,17 @@ module Coinbase
73
77
  @debug_api = false
74
78
  @use_server_signer = false
75
79
  @max_network_tries = 3
80
+ @default_network = Coinbase::Network::BASE_SEPOLIA
81
+ end
82
+
83
+ attr_reader :default_network
84
+
85
+ def default_network=(network)
86
+ unless network.is_a?(Coinbase::Network)
87
+ raise InvalidConfiguration, 'Default network must use a network constant, e.g. Coinbase::Network::BASE_MAINNET'
88
+ end
89
+
90
+ @default_network = network
76
91
  end
77
92
 
78
93
  # Sets configuration values based on the provided CDP API Key JSON file.
@@ -97,12 +112,6 @@ module Coinbase
97
112
  end
98
113
  end
99
114
 
100
- # Returns the default user.
101
- # @return [Coinbase::User] the default user
102
- def self.default_user
103
- @default_user ||= load_default_user
104
- end
105
-
106
115
  # Converts a string to a symbol, replacing hyphens with underscores.
107
116
  # @param string [String] the string to convert
108
117
  # @return [Symbol] the converted symbol
@@ -110,19 +119,14 @@ module Coinbase
110
119
  value.to_s.gsub('-', '_').to_sym
111
120
  end
112
121
 
113
- # Converts a network symbol to a string, replacing underscores with hyphens.
114
- # @param network_sym [Symbol] the network symbol to convert
115
- # @return [String] the converted string
116
- def self.normalize_network(network_sym)
117
- network_sym.to_s.gsub('_', '-')
118
- end
122
+ # Converts a Network object or network symbol with the string representation of the network ID,
123
+ # replacing underscores with hyphens.
124
+ # @param network_sym [Coinbase::Network, Symbol] The network or network symbol to convert
125
+ # @return [String] The string representation of the network ID
126
+ def self.normalize_network(network)
127
+ network_sym = network.is_a?(Coinbase::Network) ? network.id : network
119
128
 
120
- # Loads the default user.
121
- # @return [Coinbase::User] the default user
122
- def self.load_default_user
123
- users_api = Coinbase::Client::UsersApi.new(configuration.api_client)
124
- user_model = users_api.get_current_user
125
- Coinbase::User.new(user_model)
129
+ network_sym.to_s.gsub('_', '-')
126
130
  end
127
131
 
128
132
  # Wraps a call to the Platform API to ensure that the error is caught and
@@ -150,9 +154,36 @@ module Coinbase
150
154
  Coinbase.configuration.use_server_signer
151
155
  end
152
156
 
157
+ # Returns the default network.
158
+ # @return [Coinbase::Network] the default network
159
+ def self.default_network
160
+ Coinbase.configuration.default_network
161
+ end
162
+
153
163
  # Returns whether the SDK is configured.
154
164
  # @return [bool] whether the SDK is configured
155
165
  def self.configured?
156
166
  !Coinbase.configuration.api_key_name.nil? && !Coinbase.configuration.api_key_private_key.nil?
157
167
  end
158
168
  end
169
+
170
+ # Initialize the Network constants.
171
+ Coinbase::Network.const_set(
172
+ 'ALL',
173
+ Coinbase::Client::NetworkIdentifier.all_vars.each_with_object([]) do |id, list|
174
+ next if id == Coinbase::Client::NetworkIdentifier::UNKNOWN_DEFAULT_OPEN_API
175
+
176
+ network = Coinbase::Network.new(id)
177
+
178
+ Coinbase::Network.const_set(id.upcase.gsub('-', '_'), network)
179
+
180
+ list << network
181
+ end
182
+ )
183
+
184
+ Coinbase::Network.const_set(
185
+ 'NETWORK_MAP',
186
+ Coinbase::Network::ALL.each_with_object({}) do |network, map|
187
+ map[network.id] = network
188
+ end
189
+ )