coinbase-sdk 0.0.16 → 0.1.0

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