coinbase-sdk 0.11.0 → 0.14.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 (50) hide show
  1. checksums.yaml +4 -4
  2. data/lib/coinbase/address/wallet_address.rb +6 -3
  3. data/lib/coinbase/address.rb +22 -3
  4. data/lib/coinbase/address_reputation.rb +67 -0
  5. data/lib/coinbase/client/api/addresses_api.rb +9 -9
  6. data/lib/coinbase/client/api/assets_api.rb +1 -1
  7. data/lib/coinbase/client/api/balance_history_api.rb +1 -1
  8. data/lib/coinbase/client/api/contract_events_api.rb +1 -1
  9. data/lib/coinbase/client/api/contract_invocations_api.rb +4 -4
  10. data/lib/coinbase/client/api/external_addresses_api.rb +245 -4
  11. data/lib/coinbase/client/api/fund_api.rb +4 -4
  12. data/lib/coinbase/client/api/mpc_wallet_stake_api.rb +3 -3
  13. data/lib/coinbase/client/api/networks_api.rb +1 -1
  14. data/lib/coinbase/client/api/onchain_identity_api.rb +1 -1
  15. data/lib/coinbase/client/api/reputation_api.rb +1 -70
  16. data/lib/coinbase/client/api/server_signers_api.rb +6 -6
  17. data/lib/coinbase/client/api/smart_contracts_api.rb +168 -25
  18. data/lib/coinbase/client/api/stake_api.rb +7 -7
  19. data/lib/coinbase/client/api/trades_api.rb +4 -4
  20. data/lib/coinbase/client/api/transaction_history_api.rb +1 -1
  21. data/lib/coinbase/client/api/transfers_api.rb +4 -4
  22. data/lib/coinbase/client/api/wallets_api.rb +5 -5
  23. data/lib/coinbase/client/api/webhooks_api.rb +5 -5
  24. data/lib/coinbase/client/configuration.rb +14 -0
  25. data/lib/coinbase/client/models/address_reputation.rb +15 -8
  26. data/lib/coinbase/client/models/{address_risk.rb → broadcast_external_transfer_request.rb} +15 -16
  27. data/lib/coinbase/client/models/create_external_transfer_request.rb +283 -0
  28. data/lib/coinbase/client/models/create_fund_operation_request.rb +1 -1
  29. data/lib/coinbase/client/models/create_fund_quote_request.rb +1 -1
  30. data/lib/coinbase/client/models/create_transfer_request.rb +15 -5
  31. data/lib/coinbase/client/models/ethereum_transaction.rb +14 -4
  32. data/lib/coinbase/client/models/register_smart_contract_request.rb +252 -0
  33. data/lib/coinbase/client/models/smart_contract.rb +36 -30
  34. data/lib/coinbase/client/models/smart_contract_activity_event.rb +386 -0
  35. data/lib/coinbase/client/models/smart_contract_type.rb +2 -1
  36. data/lib/coinbase/client/models/transfer.rb +1 -36
  37. data/lib/coinbase/client/models/update_smart_contract_request.rb +245 -0
  38. data/lib/coinbase/client/models/webhook_event_type.rb +2 -1
  39. data/lib/coinbase/client/models/webhook_event_type_filter.rb +1 -0
  40. data/lib/coinbase/client/models/webhook_smart_contract_event_filter.rb +225 -0
  41. data/lib/coinbase/client/models/webhook_wallet_activity_filter.rb +7 -0
  42. data/lib/coinbase/client.rb +6 -1
  43. data/lib/coinbase/errors.rb +8 -0
  44. data/lib/coinbase/smart_contract.rb +338 -245
  45. data/lib/coinbase/transfer.rb +24 -2
  46. data/lib/coinbase/version.rb +1 -1
  47. data/lib/coinbase/wallet/data.rb +6 -4
  48. data/lib/coinbase/wallet.rb +3 -2
  49. data/lib/coinbase.rb +2 -1
  50. metadata +13 -7
@@ -2,257 +2,311 @@
2
2
 
3
3
  module Coinbase
4
4
  # A representation of a SmartContract on the blockchain.
5
+ # rubocop:disable Metrics/ClassLength
5
6
  class SmartContract
6
- # Returns a list of ContractEvents for the provided network, contract, and event details.
7
- # @param network_id [Symbol] The network ID
8
- # @param protocol_name [String] The protocol name
9
- # @param contract_address [String] The contract address
10
- # @param contract_name [String] The contract name
11
- # @param event_name [String] The event name
12
- # @param from_block_height [Integer] The start block height
13
- # @param to_block_height [Integer] The end block height
14
- # @return [Enumerable<Coinbase::ContractEvent>] The contract events
15
- def self.list_events(
16
- network_id:,
17
- protocol_name:,
18
- contract_address:,
19
- contract_name:,
20
- event_name:,
21
- from_block_height:,
22
- to_block_height:
23
- )
24
- Coinbase::Pagination.enumerate(
25
- lambda { |page|
26
- list_events_page(
27
- network_id,
28
- protocol_name,
29
- contract_address,
30
- contract_name,
31
- event_name,
32
- from_block_height,
33
- to_block_height,
34
- page
35
- )
36
- }
37
- ) do |contract_event|
38
- Coinbase::ContractEvent.new(contract_event)
7
+ class << self
8
+ # Returns a list of ContractEvents for the provided network, contract, and event details.
9
+ # @param network_id [Symbol] The network ID
10
+ # @param protocol_name [String] The protocol name
11
+ # @param contract_address [String] The contract address
12
+ # @param contract_name [String] The contract name
13
+ # @param event_name [String] The event name
14
+ # @param from_block_height [Integer] The start block height
15
+ # @param to_block_height [Integer] The end block height
16
+ # @return [Enumerable<Coinbase::ContractEvent>] The contract events
17
+ def list_events(
18
+ network_id:,
19
+ protocol_name:,
20
+ contract_address:,
21
+ contract_name:,
22
+ event_name:,
23
+ from_block_height:,
24
+ to_block_height:
25
+ )
26
+ Coinbase::Pagination.enumerate(
27
+ lambda { |page|
28
+ list_events_page(
29
+ network_id,
30
+ protocol_name,
31
+ contract_address,
32
+ contract_name,
33
+ event_name,
34
+ from_block_height,
35
+ to_block_height,
36
+ page
37
+ )
38
+ }
39
+ ) do |contract_event|
40
+ Coinbase::ContractEvent.new(contract_event)
41
+ end
39
42
  end
40
- end
41
43
 
42
- # Creates a new ERC20 token contract, that can subsequently be deployed to
43
- # the blockchain.
44
- # @param address_id [String] The address ID of deployer
45
- # @param wallet_id [String] The wallet ID of the deployer
46
- # @param name [String] The name of the token
47
- # @param symbol [String] The symbol of the token
48
- # @param total_supply [String] The total supply of the token, denominate in whole units.
49
- # @return [SmartContract] The new ERC20 Token SmartContract object
50
- def self.create_token_contract(
51
- address_id:,
52
- wallet_id:,
53
- name:,
54
- symbol:,
55
- total_supply:
56
- )
57
- contract = Coinbase.call_api do
58
- smart_contracts_api.create_smart_contract(
59
- wallet_id,
60
- address_id,
61
- {
62
- type: Coinbase::Client::SmartContractType::ERC20,
63
- options: Coinbase::Client::TokenContractOptions.new(
64
- name: name,
65
- symbol: symbol,
66
- total_supply: BigDecimal(total_supply).to_i.to_s
67
- ).to_body
68
- }
69
- )
44
+ # Creates a new ERC20 token contract, that can subsequently be deployed to
45
+ # the blockchain.
46
+ # @param address_id [String] The address ID of deployer
47
+ # @param wallet_id [String] The wallet ID of the deployer
48
+ # @param name [String] The name of the token
49
+ # @param symbol [String] The symbol of the token
50
+ # @param total_supply [String] The total supply of the token, denominate in whole units.
51
+ # @return [SmartContract] The new ERC20 Token SmartContract object
52
+ def create_token_contract(
53
+ address_id:,
54
+ wallet_id:,
55
+ name:,
56
+ symbol:,
57
+ total_supply:
58
+ )
59
+ contract = Coinbase.call_api do
60
+ smart_contracts_api.create_smart_contract(
61
+ wallet_id,
62
+ address_id,
63
+ {
64
+ type: Coinbase::Client::SmartContractType::ERC20,
65
+ options: Coinbase::Client::TokenContractOptions.new(
66
+ name: name,
67
+ symbol: symbol,
68
+ total_supply: BigDecimal(total_supply).to_i.to_s
69
+ ).to_body
70
+ }
71
+ )
72
+ end
73
+
74
+ new(contract)
70
75
  end
71
76
 
72
- new(contract)
73
- end
77
+ # Creates a new ERC721 token contract, that can subsequently be deployed to
78
+ # the blockchain.
79
+ # @param address_id [String] The address ID of deployer
80
+ # @param wallet_id [String] The wallet ID of the deployer
81
+ # @param name [String] The name of the token
82
+ # @param symbol [String] The symbol of the token
83
+ # @param base_uri [String] The base URI for the token metadata
84
+ # @return [SmartContract] The new ERC721 Token SmartContract object
85
+ def create_nft_contract(
86
+ address_id:,
87
+ wallet_id:,
88
+ name:,
89
+ symbol:,
90
+ base_uri:
91
+ )
92
+ contract = Coinbase.call_api do
93
+ smart_contracts_api.create_smart_contract(
94
+ wallet_id,
95
+ address_id,
96
+ {
97
+ type: Coinbase::Client::SmartContractType::ERC721,
98
+ options: Coinbase::Client::NFTContractOptions.new(
99
+ name: name,
100
+ symbol: symbol,
101
+ base_uri: base_uri
102
+ ).to_body
103
+ }
104
+ )
105
+ end
74
106
 
75
- # Creates a new ERC721 token contract, that can subsequently be deployed to
76
- # the blockchain.
77
- # @param address_id [String] The address ID of deployer
78
- # @param wallet_id [String] The wallet ID of the deployer
79
- # @param name [String] The name of the token
80
- # @param symbol [String] The symbol of the token
81
- # @param base_uri [String] The base URI for the token metadata
82
- # @return [SmartContract] The new ERC721 Token SmartContract object
83
- def self.create_nft_contract(
84
- address_id:,
85
- wallet_id:,
86
- name:,
87
- symbol:,
88
- base_uri:
89
- )
90
- contract = Coinbase.call_api do
91
- smart_contracts_api.create_smart_contract(
92
- wallet_id,
93
- address_id,
94
- {
95
- type: Coinbase::Client::SmartContractType::ERC721,
96
- options: Coinbase::Client::NFTContractOptions.new(
97
- name: name,
98
- symbol: symbol,
99
- base_uri: base_uri
100
- ).to_body
101
- }
102
- )
107
+ new(contract)
103
108
  end
104
109
 
105
- new(contract)
106
- end
110
+ # Creates a new ERC1155 multi-token contract, that can subsequently be deployed to
111
+ # the blockchain.
112
+ # @param address_id [String] The address ID of deployer
113
+ # @param wallet_id [String] The wallet ID of the deployer
114
+ # @param uri [String] The URI for the token metadata
115
+ # @return [SmartContract] The new ERC1155 Multi-Token SmartContract object
116
+ def create_multi_token_contract(
117
+ address_id:,
118
+ wallet_id:,
119
+ uri:
120
+ )
121
+ contract = Coinbase.call_api do
122
+ smart_contracts_api.create_smart_contract(
123
+ wallet_id,
124
+ address_id,
125
+ {
126
+ type: Coinbase::Client::SmartContractType::ERC1155,
127
+ options: Coinbase::Client::MultiTokenContractOptions.new(
128
+ uri: uri
129
+ ).to_body
130
+ }
131
+ )
132
+ end
107
133
 
108
- # Creates a new ERC1155 multi-token contract, that can subsequently be deployed to
109
- # the blockchain.
110
- # @param address_id [String] The address ID of deployer
111
- # @param wallet_id [String] The wallet ID of the deployer
112
- # @param uri [String] The URI for the token metadata
113
- # @return [SmartContract] The new ERC1155 Multi-Token SmartContract object
114
- def self.create_multi_token_contract(
115
- address_id:,
116
- wallet_id:,
117
- uri:
118
- )
119
- contract = Coinbase.call_api do
120
- smart_contracts_api.create_smart_contract(
121
- wallet_id,
122
- address_id,
123
- {
124
- type: Coinbase::Client::SmartContractType::ERC1155,
125
- options: Coinbase::Client::MultiTokenContractOptions.new(
126
- uri: uri
127
- ).to_body
128
- }
129
- )
134
+ new(contract)
130
135
  end
131
136
 
132
- new(contract)
133
- end
137
+ # Registers an externally deployed smart contract with the API.
138
+ # @param contract_address [String] The address of the deployed contract
139
+ # @param abi [Array, String] The ABI of the contract
140
+ # @param network [Coinbase::Network, Symbol] The Network or Network ID the contract is deployed on
141
+ # @param name [String, nil] The optional name of the contract
142
+ def register(
143
+ contract_address:,
144
+ abi:,
145
+ name: nil,
146
+ network: Coinbase.default_network
147
+ )
148
+ network = Coinbase::Network.from_id(network)
134
149
 
135
- # Reads data from a deployed smart contract.
136
- #
137
- # @param network [Coinbase::Network, Symbol] The Network or Network ID of the Asset
138
- # @param contract_address [String] The address of the deployed contract
139
- # @param method [String] The name of the method to call on the contract
140
- # @param abi [Array, nil] The ABI of the contract. If nil, the method will attempt to use a cached ABI
141
- # @param args [Hash] The arguments to pass to the contract method.
142
- # The keys should be the argument names, and the values should be the argument values.
143
- # @return [Object] The result of the contract call, converted to an appropriate Ruby type
144
- # @raise [Coinbase::ApiError] If there's an error in the API call
145
- def self.read(
146
- contract_address:,
147
- method:,
148
- network: Coinbase.default_network,
149
- abi: nil,
150
- args: {}
151
- )
152
- network = Coinbase::Network.from_id(network)
153
-
154
- response = Coinbase.call_api do
155
- smart_contracts_api.read_contract(
156
- network.normalized_id,
157
- contract_address,
158
- {
159
- method: method,
160
- args: (args || {}).to_json,
161
- abi: abi&.to_json
162
- }.compact
163
- )
150
+ normalized_abi = normalize_abi(abi)
151
+
152
+ smart_contract = Coinbase.call_api do
153
+ smart_contracts_api.register_smart_contract(
154
+ network.normalized_id,
155
+ contract_address,
156
+ register_smart_contract_request: {
157
+ abi: normalized_abi.to_json,
158
+ contract_name: name
159
+ }.compact
160
+ )
161
+ end
162
+
163
+ new(smart_contract)
164
164
  end
165
165
 
166
- convert_solidity_value(response)
167
- end
166
+ # Reads data from a deployed smart contract.
167
+ #
168
+ # @param network [Coinbase::Network, Symbol] The Network or Network ID of the Asset
169
+ # @param contract_address [String] The address of the deployed contract
170
+ # @param method [String] The name of the method to call on the contract
171
+ # @param abi [Array, nil] The ABI of the contract. If nil, the method will attempt to use a cached ABI
172
+ # @param args [Hash] The arguments to pass to the contract method.
173
+ # The keys should be the argument names, and the values should be the argument values.
174
+ # @return [Object] The result of the contract call, converted to an appropriate Ruby type
175
+ # @raise [Coinbase::ApiError] If there's an error in the API call
176
+ def read(
177
+ contract_address:,
178
+ method:,
179
+ network: Coinbase.default_network,
180
+ abi: nil,
181
+ args: {}
182
+ )
183
+ network = Coinbase::Network.from_id(network)
168
184
 
169
- # Converts a Solidity value to an appropriate Ruby type.
170
- #
171
- # @param solidity_value [Coinbase::Client::SolidityValue] The Solidity value to convert
172
- # @return [Object] The converted Ruby value
173
- # @raise [ArgumentError] If an unsupported Solidity type is encountered
174
- #
175
- # This method handles the following Solidity types:
176
- # - Integers (uint8, uint16, uint32, uint64, uint128, uint256, int8, int16, int32, int64, int128, int256)
177
- # - Address
178
- # - String
179
- # - Bytes (including fixed-size byte arrays)
180
- # - Boolean
181
- # - Array
182
- # - Tuple (converted to a Hash)
183
- #
184
- # For complex types like arrays and tuples, the method recursively converts nested values.
185
- def self.convert_solidity_value(solidity_value)
186
- return nil if solidity_value.nil?
187
-
188
- type = solidity_value.type
189
- value = solidity_value.value
190
- values = solidity_value.values
191
-
192
- case type
193
- when 'uint8', 'uint16', 'uint32', 'uint64', 'uint128', 'uint256',
194
- 'int8', 'int16', 'int32', 'int64', 'int128', 'int256'
195
- value&.to_i
196
- when 'address', 'string', /^bytes/
197
- value
198
- when 'bool'
199
- if value.is_a?(String)
200
- value == 'true'
201
- else
202
- !value.nil?
185
+ response = Coinbase.call_api do
186
+ smart_contracts_api.read_contract(
187
+ network.normalized_id,
188
+ contract_address,
189
+ {
190
+ method: method,
191
+ args: (args || {}).to_json,
192
+ abi: abi&.to_json
193
+ }.compact
194
+ )
203
195
  end
204
- when 'array'
205
- values ? values.map { |v| convert_solidity_value(v) } : []
206
- when 'tuple'
207
- if values
208
- result = {}
209
- values.each do |v|
210
- raise ArgumentError, 'Error: Tuple value without a name' unless v.respond_to?(:name)
211
-
212
- result[v.name] = convert_solidity_value(v)
196
+
197
+ convert_solidity_value(response)
198
+ end
199
+
200
+ def list
201
+ Coinbase::Pagination.enumerate(
202
+ lambda { |page|
203
+ smart_contracts_api.list_smart_contracts(page: page)
204
+ }
205
+ ) do |smart_contract|
206
+ new(smart_contract)
207
+ end
208
+ end
209
+
210
+ # Normalizes an ABI from a String or Array of Hashes to an Array of Hashes.
211
+ # @param abi [String, Array] The ABI to normalize
212
+ # @return [Array<Hash>] The normalized ABI
213
+ # @raise [ArgumentError] If the ABI is not a valid JSON string or Array
214
+ def normalize_abi(abi)
215
+ return abi if abi.is_a?(Array)
216
+
217
+ raise ArgumentError, 'ABI must be an Array or a JSON string' unless abi.is_a?(String)
218
+
219
+ JSON.parse(abi)
220
+ rescue JSON::ParserError
221
+ raise ArgumentError, 'Invalid ABI JSON'
222
+ end
223
+
224
+ private
225
+
226
+ # Converts a Solidity value to an appropriate Ruby type.
227
+ #
228
+ # @param solidity_value [Coinbase::Client::SolidityValue] The Solidity value to convert
229
+ # @return [Object] The converted Ruby value
230
+ # @raise [ArgumentError] If an unsupported Solidity type is encountered
231
+ #
232
+ # This method handles the following Solidity types:
233
+ # - Integers (uint8, uint16, uint32, uint64, uint128, uint256, int8, int16, int32, int64, int128, int256)
234
+ # - Address
235
+ # - String
236
+ # - Bytes (including fixed-size byte arrays)
237
+ # - Boolean
238
+ # - Array
239
+ # - Tuple (converted to a Hash)
240
+ #
241
+ # For complex types like arrays and tuples, the method recursively converts nested values.
242
+ def convert_solidity_value(solidity_value)
243
+ return nil if solidity_value.nil?
244
+
245
+ type = solidity_value.type
246
+ value = solidity_value.value
247
+ values = solidity_value.values
248
+
249
+ case type
250
+ when 'uint8', 'uint16', 'uint32', 'uint64', 'uint128', 'uint256',
251
+ 'int8', 'int16', 'int32', 'int64', 'int128', 'int256'
252
+ value&.to_i
253
+ when 'address', 'string', /^bytes/
254
+ value
255
+ when 'bool'
256
+ if value.is_a?(String)
257
+ value == 'true'
258
+ else
259
+ !value.nil?
260
+ end
261
+ when 'array'
262
+ values ? values.map { |v| convert_solidity_value(v) } : []
263
+ when 'tuple'
264
+ if values
265
+ result = {}
266
+ values.each do |v|
267
+ raise ArgumentError, 'Error: Tuple value without a name' unless v.respond_to?(:name)
268
+
269
+ result[v.name] = convert_solidity_value(v)
270
+ end
271
+ result
272
+ else
273
+ {}
213
274
  end
214
- result
215
275
  else
216
- {}
276
+ raise ArgumentError, "Unsupported Solidity type: #{type}"
217
277
  end
218
- else
219
- raise ArgumentError, "Unsupported Solidity type: #{type}"
220
278
  end
221
- end
222
- private_class_method :convert_solidity_value
223
279
 
224
- def self.contract_events_api
225
- Coinbase::Client::ContractEventsApi.new(Coinbase.configuration.api_client)
226
- end
227
- private_class_method :contract_events_api
280
+ def contract_events_api
281
+ Coinbase::Client::ContractEventsApi.new(Coinbase.configuration.api_client)
282
+ end
228
283
 
229
- def self.smart_contracts_api
230
- Coinbase::Client::SmartContractsApi.new(Coinbase.configuration.api_client)
231
- end
232
- private_class_method :smart_contracts_api
233
-
234
- def self.list_events_page(
235
- network_id,
236
- protocol_name,
237
- contract_address,
238
- contract_name,
239
- event_name,
240
- from_block_height,
241
- to_block_height,
242
- page
243
- )
244
- contract_events_api.list_contract_events(
245
- Coinbase.normalize_network(network_id),
284
+ def smart_contracts_api
285
+ Coinbase::Client::SmartContractsApi.new(Coinbase.configuration.api_client)
286
+ end
287
+
288
+ def list_events_page(
289
+ network_id,
246
290
  protocol_name,
247
291
  contract_address,
248
292
  contract_name,
249
293
  event_name,
250
294
  from_block_height,
251
295
  to_block_height,
252
- { next_page: page }
296
+ page
253
297
  )
298
+ contract_events_api.list_contract_events(
299
+ Coinbase.normalize_network(network_id),
300
+ protocol_name,
301
+ contract_address,
302
+ contract_name,
303
+ event_name,
304
+ from_block_height,
305
+ to_block_height,
306
+ { next_page: page }
307
+ )
308
+ end
254
309
  end
255
- private_class_method :list_events_page
256
310
 
257
311
  # Returns a new SmartContract object.
258
312
  # @param model [Coinbase::Client::SmartContract] The underlying SmartContract object
@@ -282,8 +336,15 @@ module Coinbase
282
336
  @model.contract_address
283
337
  end
284
338
 
285
- # Returns the address of the deployer of the SmartContract.
286
- # @return [String] The deployer address
339
+ # Returns the name of the SmartContract.
340
+ # @return [String] The contract name
341
+ def name
342
+ @model.contract_name
343
+ end
344
+
345
+ # Returns the address of the deployer of the SmartContract, if deployed via CDP.
346
+ # Returns nil for externally registered contracts.
347
+ # @return [String, nil] The deployer address
287
348
  def deployer_address
288
349
  @model.deployer_address
289
350
  end
@@ -294,7 +355,8 @@ module Coinbase
294
355
  JSON.parse(@model.abi)
295
356
  end
296
357
 
297
- # Returns the ID of the wallet that deployed the SmartContract.
358
+ # Returns the ID of the wallet that deployed the SmartContract, if deployed via CDP.
359
+ # Returns nil for externally registered contracts.
298
360
  # @return [String] The wallet ID
299
361
  def wallet_id
300
362
  @model.wallet_id
@@ -306,22 +368,45 @@ module Coinbase
306
368
  @model.type
307
369
  end
308
370
 
309
- # Returns the options of the SmartContract.
310
- # @return [Coinbase::Client::SmartContractOptions] The SmartContract options
371
+ # Returns the options of the SmartContract, if deployed via CDP.
372
+ # Returns nil for externally registered contracts.
373
+ # @return [Coinbase::Client::SmartContractOptions, nil] The SmartContract options
311
374
  def options
312
375
  @model.options
313
376
  end
314
377
 
315
- # Returns the transaction.
316
- # @return [Coinbase::Transaction] The SmartContracy deployment transaction
378
+ # Returns whether the SmartContract is an externally registered contract or a CDP managed contract.
379
+ # @return [Boolean] Whether the SmartContract is external
380
+ def external?
381
+ @model.is_external
382
+ end
383
+
384
+ # Returns the transaction, if deployed via CDP.
385
+ # @return [Coinbase::Transaction] The SmartContract deployment transaction
317
386
  def transaction
318
- @transaction ||= Coinbase::Transaction.new(@model.transaction)
387
+ @transaction ||= @model.transaction.nil? ? nil : Coinbase::Transaction.new(@model.transaction)
319
388
  end
320
389
 
321
- # Returns the status of the SmartContract.
390
+ # Returns the status of the SmartContract, if deployed via CDP.
322
391
  # @return [String] The status
323
392
  def status
324
- transaction.status
393
+ transaction&.status
394
+ end
395
+
396
+ def update(name: nil, abi: nil)
397
+ req = {}
398
+ req[:contract_name] = name unless name.nil?
399
+ req[:abi] = self.class.normalize_abi(abi).to_json unless abi.nil?
400
+
401
+ @model = Coinbase.call_api do
402
+ smart_contracts_api.update_smart_contract(
403
+ network.normalized_id,
404
+ contract_address,
405
+ update_smart_contract_request: req
406
+ )
407
+ end
408
+
409
+ self
325
410
  end
326
411
 
327
412
  # Signs the SmartContract deployment transaction with the given key.
@@ -329,8 +414,10 @@ module Coinbase
329
414
  # @param key [Eth::Key] The key to sign the SmartContract with
330
415
  # @return [SmartContract] The SmartContract object
331
416
  # @raise [RuntimeError] If the key is not an Eth::Key
417
+ # @raise [RuntimeError] If the SmartContract is external
332
418
  # @raise [Coinbase::AlreadySignedError] If the SmartContract has already been signed
333
419
  def sign(key)
420
+ raise ManageExternalContractError, 'sign' if external?
334
421
  raise unless key.is_a?(Eth::Key)
335
422
 
336
423
  transaction.sign(key)
@@ -339,7 +426,9 @@ module Coinbase
339
426
  # Deploys the signed SmartContract to the blockchain.
340
427
  # @return [SmartContract] The SmartContract object
341
428
  # @raise [Coinbase::TransactionNotSignedError] If the SmartContract has not been signed
429
+ # @raise [RuntimeError] If the SmartContract is external
342
430
  def deploy!
431
+ raise ManageExternalContractError, 'deploy' if external?
343
432
  raise TransactionNotSignedError unless transaction.signed?
344
433
 
345
434
  @model = Coinbase.call_api do
@@ -359,15 +448,13 @@ module Coinbase
359
448
  # Reloads the Smart Contract model with the latest version from the server side.
360
449
  # @return [SmartContract] The most recent version of Smart Contract from the server
361
450
  def reload
451
+ raise ManageExternalContractError, 'reload' if external?
452
+
362
453
  @model = Coinbase.call_api do
363
- smart_contracts_api.get_smart_contract(
364
- wallet_id,
365
- deployer_address,
366
- id
367
- )
454
+ smart_contracts_api.get_smart_contract(wallet_id, deployer_address, id)
368
455
  end
369
456
 
370
- @transaction = Coinbase::Transaction.new(@model.transaction)
457
+ @transaction = Coinbase::Transaction.new(@model.transaction) if @model.transaction
371
458
 
372
459
  self
373
460
  end
@@ -379,6 +466,8 @@ module Coinbase
379
466
  # @return [SmartContract] The completed Smart Contract object
380
467
  # @raise [Timeout::Error] if the Contract Invocation takes longer than the given timeout
381
468
  def wait!(interval_seconds = 0.2, timeout_seconds = 20)
469
+ raise ManageExternalContractError, 'wait!' if external?
470
+
382
471
  start_time = Time.now
383
472
 
384
473
  loop do
@@ -387,8 +476,7 @@ module Coinbase
387
476
  return self if transaction.terminal_state?
388
477
 
389
478
  if Time.now - start_time > timeout_seconds
390
- raise Timeout::Error,
391
- 'SmartContract deployment timed out. Try waiting again.'
479
+ raise Timeout::Error, 'SmartContract deployment timed out. Try waiting again.'
392
480
  end
393
481
 
394
482
  self.sleep interval_seconds
@@ -408,12 +496,16 @@ module Coinbase
408
496
  def to_s
409
497
  Coinbase.pretty_print_object(
410
498
  self.class,
411
- network: network.id,
412
- contract_address: contract_address,
413
- deployer_address: deployer_address,
414
- type: type,
415
- status: status,
416
- options: Coinbase.pretty_print_object('Options', **options)
499
+ **{
500
+ network: network.id,
501
+ contract_address: contract_address,
502
+ type: type,
503
+ name: name,
504
+ # Fields only present for CDP managed contracts.
505
+ status: status,
506
+ deployer_address: deployer_address,
507
+ options: options.nil? ? nil : Coinbase.pretty_print_object('Options', **options)
508
+ }.compact
417
509
  )
418
510
  end
419
511
 
@@ -423,4 +515,5 @@ module Coinbase
423
515
  @smart_contracts_api ||= Coinbase::Client::SmartContractsApi.new(Coinbase.configuration.api_client)
424
516
  end
425
517
  end
518
+ # rubocop:enable Metrics/ClassLength
426
519
  end