coinbase-sdk 0.11.0 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (151) hide show
  1. checksums.yaml +4 -4
  2. data/lib/coinbase/address.rb +22 -3
  3. data/lib/coinbase/address_reputation.rb +67 -0
  4. data/lib/coinbase/client/api/addresses_api.rb +10 -10
  5. data/lib/coinbase/client/api/assets_api.rb +2 -2
  6. data/lib/coinbase/client/api/balance_history_api.rb +2 -2
  7. data/lib/coinbase/client/api/contract_events_api.rb +2 -2
  8. data/lib/coinbase/client/api/contract_invocations_api.rb +5 -5
  9. data/lib/coinbase/client/api/external_addresses_api.rb +246 -5
  10. data/lib/coinbase/client/api/fund_api.rb +5 -5
  11. data/lib/coinbase/client/api/mpc_wallet_stake_api.rb +4 -4
  12. data/lib/coinbase/client/api/networks_api.rb +2 -2
  13. data/lib/coinbase/client/api/onchain_identity_api.rb +2 -2
  14. data/lib/coinbase/client/api/reputation_api.rb +2 -71
  15. data/lib/coinbase/client/api/server_signers_api.rb +7 -7
  16. data/lib/coinbase/client/api/smart_contracts_api.rb +169 -26
  17. data/lib/coinbase/client/api/stake_api.rb +8 -8
  18. data/lib/coinbase/client/api/trades_api.rb +5 -5
  19. data/lib/coinbase/client/api/transaction_history_api.rb +2 -2
  20. data/lib/coinbase/client/api/transfers_api.rb +14 -14
  21. data/lib/coinbase/client/api/users_api.rb +1 -1
  22. data/lib/coinbase/client/api/wallets_api.rb +6 -6
  23. data/lib/coinbase/client/api/webhooks_api.rb +6 -6
  24. data/lib/coinbase/client/api_client.rb +1 -1
  25. data/lib/coinbase/client/api_error.rb +1 -1
  26. data/lib/coinbase/client/configuration.rb +15 -1
  27. data/lib/coinbase/client/models/address.rb +1 -1
  28. data/lib/coinbase/client/models/address_balance_list.rb +1 -1
  29. data/lib/coinbase/client/models/address_historical_balance_list.rb +1 -1
  30. data/lib/coinbase/client/models/address_list.rb +1 -1
  31. data/lib/coinbase/client/models/address_reputation.rb +16 -9
  32. data/lib/coinbase/client/models/address_reputation_metadata.rb +1 -1
  33. data/lib/coinbase/client/models/address_transaction_list.rb +1 -1
  34. data/lib/coinbase/client/models/asset.rb +1 -1
  35. data/lib/coinbase/client/models/balance.rb +1 -1
  36. data/lib/coinbase/client/models/broadcast_contract_invocation_request.rb +1 -1
  37. data/lib/coinbase/client/models/{broadcast_transfer_request.rb → broadcast_external_transfer_request.rb} +4 -4
  38. data/lib/coinbase/client/models/broadcast_staking_operation_request.rb +1 -1
  39. data/lib/coinbase/client/models/broadcast_trade_request.rb +1 -1
  40. data/lib/coinbase/client/models/build_staking_operation_request.rb +1 -1
  41. data/lib/coinbase/client/models/contract_event.rb +1 -1
  42. data/lib/coinbase/client/models/contract_event_list.rb +1 -1
  43. data/lib/coinbase/client/models/contract_invocation.rb +1 -1
  44. data/lib/coinbase/client/models/contract_invocation_list.rb +1 -1
  45. data/lib/coinbase/client/models/create_address_request.rb +1 -1
  46. data/lib/coinbase/client/models/create_contract_invocation_request.rb +1 -1
  47. data/lib/coinbase/client/models/create_external_transfer_request.rb +273 -0
  48. data/lib/coinbase/client/models/create_fund_operation_request.rb +2 -2
  49. data/lib/coinbase/client/models/create_fund_quote_request.rb +2 -2
  50. data/lib/coinbase/client/models/create_payload_signature_request.rb +1 -1
  51. data/lib/coinbase/client/models/create_server_signer_request.rb +1 -1
  52. data/lib/coinbase/client/models/create_smart_contract_request.rb +1 -1
  53. data/lib/coinbase/client/models/create_staking_operation_request.rb +1 -1
  54. data/lib/coinbase/client/models/create_trade_request.rb +1 -1
  55. data/lib/coinbase/client/models/create_transfer_request.rb +2 -2
  56. data/lib/coinbase/client/models/create_wallet_request.rb +1 -1
  57. data/lib/coinbase/client/models/create_wallet_request_wallet.rb +1 -1
  58. data/lib/coinbase/client/models/create_wallet_webhook_request.rb +1 -1
  59. data/lib/coinbase/client/models/create_webhook_request.rb +1 -1
  60. data/lib/coinbase/client/models/crypto_amount.rb +1 -1
  61. data/lib/coinbase/client/models/deploy_smart_contract_request.rb +1 -1
  62. data/lib/coinbase/client/models/erc20_transfer_event.rb +1 -1
  63. data/lib/coinbase/client/models/erc721_transfer_event.rb +1 -1
  64. data/lib/coinbase/client/models/error.rb +1 -1
  65. data/lib/coinbase/client/models/ethereum_token_transfer.rb +1 -1
  66. data/lib/coinbase/client/models/ethereum_transaction.rb +15 -5
  67. data/lib/coinbase/client/models/ethereum_transaction_access.rb +1 -1
  68. data/lib/coinbase/client/models/ethereum_transaction_access_list.rb +1 -1
  69. data/lib/coinbase/client/models/ethereum_transaction_flattened_trace.rb +1 -1
  70. data/lib/coinbase/client/models/ethereum_validator_metadata.rb +1 -1
  71. data/lib/coinbase/client/models/faucet_transaction.rb +1 -1
  72. data/lib/coinbase/client/models/feature_set.rb +1 -1
  73. data/lib/coinbase/client/models/fetch_historical_staking_balances200_response.rb +1 -1
  74. data/lib/coinbase/client/models/fetch_staking_rewards200_response.rb +1 -1
  75. data/lib/coinbase/client/models/fetch_staking_rewards_request.rb +1 -1
  76. data/lib/coinbase/client/models/fiat_amount.rb +1 -1
  77. data/lib/coinbase/client/models/fund_operation.rb +1 -1
  78. data/lib/coinbase/client/models/fund_operation_fees.rb +1 -1
  79. data/lib/coinbase/client/models/fund_operation_list.rb +1 -1
  80. data/lib/coinbase/client/models/fund_quote.rb +1 -1
  81. data/lib/coinbase/client/models/get_staking_context_request.rb +1 -1
  82. data/lib/coinbase/client/models/historical_balance.rb +1 -1
  83. data/lib/coinbase/client/models/multi_token_contract_options.rb +1 -1
  84. data/lib/coinbase/client/models/network.rb +1 -1
  85. data/lib/coinbase/client/models/network_identifier.rb +1 -1
  86. data/lib/coinbase/client/models/nft_contract_options.rb +1 -1
  87. data/lib/coinbase/client/models/onchain_name.rb +1 -1
  88. data/lib/coinbase/client/models/onchain_name_list.rb +1 -1
  89. data/lib/coinbase/client/models/payload_signature.rb +1 -1
  90. data/lib/coinbase/client/models/payload_signature_list.rb +1 -1
  91. data/lib/coinbase/client/models/read_contract_request.rb +1 -1
  92. data/lib/coinbase/client/models/register_smart_contract_request.rb +252 -0
  93. data/lib/coinbase/client/models/seed_creation_event.rb +1 -1
  94. data/lib/coinbase/client/models/seed_creation_event_result.rb +1 -1
  95. data/lib/coinbase/client/models/server_signer.rb +1 -1
  96. data/lib/coinbase/client/models/server_signer_event.rb +1 -1
  97. data/lib/coinbase/client/models/server_signer_event_event.rb +1 -1
  98. data/lib/coinbase/client/models/server_signer_event_list.rb +1 -1
  99. data/lib/coinbase/client/models/server_signer_list.rb +1 -1
  100. data/lib/coinbase/client/models/signature_creation_event.rb +1 -1
  101. data/lib/coinbase/client/models/signature_creation_event_result.rb +1 -1
  102. data/lib/coinbase/client/models/signed_voluntary_exit_message_metadata.rb +1 -1
  103. data/lib/coinbase/client/models/smart_contract.rb +37 -31
  104. data/lib/coinbase/client/models/smart_contract_activity_event.rb +386 -0
  105. data/lib/coinbase/client/models/smart_contract_list.rb +1 -1
  106. data/lib/coinbase/client/models/smart_contract_options.rb +1 -1
  107. data/lib/coinbase/client/models/smart_contract_type.rb +3 -2
  108. data/lib/coinbase/client/models/solidity_value.rb +1 -1
  109. data/lib/coinbase/client/models/sponsored_send.rb +1 -1
  110. data/lib/coinbase/client/models/staking_balance.rb +1 -1
  111. data/lib/coinbase/client/models/staking_context.rb +1 -1
  112. data/lib/coinbase/client/models/staking_context_context.rb +1 -1
  113. data/lib/coinbase/client/models/staking_operation.rb +1 -1
  114. data/lib/coinbase/client/models/staking_operation_metadata.rb +1 -1
  115. data/lib/coinbase/client/models/staking_reward.rb +1 -1
  116. data/lib/coinbase/client/models/staking_reward_format.rb +1 -1
  117. data/lib/coinbase/client/models/staking_reward_usd_value.rb +1 -1
  118. data/lib/coinbase/client/models/token_contract_options.rb +1 -1
  119. data/lib/coinbase/client/models/token_transfer_type.rb +1 -1
  120. data/lib/coinbase/client/models/trade.rb +1 -1
  121. data/lib/coinbase/client/models/trade_list.rb +1 -1
  122. data/lib/coinbase/client/models/transaction.rb +1 -1
  123. data/lib/coinbase/client/models/transaction_content.rb +1 -1
  124. data/lib/coinbase/client/models/transaction_type.rb +1 -1
  125. data/lib/coinbase/client/models/transfer.rb +2 -37
  126. data/lib/coinbase/client/models/transfer_list.rb +1 -1
  127. data/lib/coinbase/client/models/update_smart_contract_request.rb +245 -0
  128. data/lib/coinbase/client/models/update_webhook_request.rb +1 -1
  129. data/lib/coinbase/client/models/user.rb +1 -1
  130. data/lib/coinbase/client/models/validator.rb +1 -1
  131. data/lib/coinbase/client/models/validator_details.rb +1 -1
  132. data/lib/coinbase/client/models/validator_list.rb +1 -1
  133. data/lib/coinbase/client/models/validator_status.rb +1 -1
  134. data/lib/coinbase/client/models/wallet.rb +1 -1
  135. data/lib/coinbase/client/models/wallet_list.rb +1 -1
  136. data/lib/coinbase/client/models/webhook.rb +1 -1
  137. data/lib/coinbase/client/models/webhook_event_filter.rb +1 -1
  138. data/lib/coinbase/client/models/webhook_event_type.rb +3 -2
  139. data/lib/coinbase/client/models/webhook_event_type_filter.rb +2 -1
  140. data/lib/coinbase/client/models/webhook_list.rb +1 -1
  141. data/lib/coinbase/client/models/{address_risk.rb → webhook_smart_contract_event_filter.rb} +19 -17
  142. data/lib/coinbase/client/models/webhook_wallet_activity_filter.rb +8 -1
  143. data/lib/coinbase/client/version.rb +1 -1
  144. data/lib/coinbase/client.rb +7 -3
  145. data/lib/coinbase/errors.rb +8 -0
  146. data/lib/coinbase/smart_contract.rb +338 -245
  147. data/lib/coinbase/version.rb +1 -1
  148. data/lib/coinbase/wallet/data.rb +6 -4
  149. data/lib/coinbase/wallet.rb +3 -2
  150. data/lib/coinbase.rb +2 -1
  151. metadata +12 -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