Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support requesting faucet funds for address #24

Merged
merged 2 commits into from
May 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## Unreleased

- Faucet
- Trade
- Individual private key export
- Allow disabling debug tracing
Expand All @@ -18,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added

- Coinbase.configure_from_file
- Faucet

## [0.0.2] - 2024-05-01

Expand Down
2 changes: 2 additions & 0 deletions lib/coinbase.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
require_relative 'coinbase/client'
require_relative 'coinbase/constants'
require_relative 'coinbase/errors'
require_relative 'coinbase/faucet_transaction'
require_relative 'coinbase/middleware'
require_relative 'coinbase/network'
require_relative 'coinbase/transfer'
Expand All @@ -17,6 +18,7 @@
# The Coinbase SDK.
module Coinbase
class InvalidConfiguration < StandardError; end
class FaucetLimitReached < StandardError; end

# Returns the configuration object.
# @return [Configuration] the configuration object
Expand Down
11 changes: 11 additions & 0 deletions lib/coinbase/address.rb
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,17 @@ def to_s
address_id
end

# Requests funds for the address from the faucet and returns the faucet transaction.
# This is only supported on testnet networks.
# @return [Coinbase::FaucetTransaction] The successful faucet transaction
# @raise [Coinbase::FaucetLimitReached] If the faucet limit has been reached for the address or user.
# @raise [Coinbase::Client::ApiError] If an unexpected error occurs while requesting faucet funds.
def faucet

This comment was marked as resolved.

Coinbase.call_api do
Coinbase::FaucetTransaction.new(addresses_api.request_faucet_funds(wallet_id, address_id))
end
end

private

# Normalizes the amount of the Asset to send to the atomic unit.
Expand Down
1 change: 1 addition & 0 deletions lib/coinbase/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
Coinbase::Client.autoload :CreateTransferRequest, 'coinbase/client/models/create_transfer_request'
Coinbase::Client.autoload :CreateWalletRequest, 'coinbase/client/models/create_wallet_request'
Coinbase::Client.autoload :Error, 'coinbase/client/models/error'
Coinbase::Client.autoload :FaucetTransaction, 'coinbase/client/models/faucet_transaction'
Coinbase::Client.autoload :Transfer, 'coinbase/client/models/transfer'
Coinbase::Client.autoload :TransferList, 'coinbase/client/models/transfer_list'
Coinbase::Client.autoload :User, 'coinbase/client/models/user'
Expand Down
69 changes: 69 additions & 0 deletions lib/coinbase/client/api/addresses_api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -381,5 +381,74 @@ def list_addresses_with_http_info(wallet_id, opts = {})
end
return data, status_code, headers
end

# Request faucet funds for onchain address.
# Request faucet funds to be sent to onchain address.
# @param wallet_id [String] The ID of the wallet the address belongs to.
# @param address_id [String] The onchain address of the address that is being fetched.
# @param [Hash] opts the optional parameters
# @return [FaucetTransaction]
def request_faucet_funds(wallet_id, address_id, opts = {})
data, _status_code, _headers = request_faucet_funds_with_http_info(wallet_id, address_id, opts)
data
end

# Request faucet funds for onchain address.
# Request faucet funds to be sent to onchain address.
# @param wallet_id [String] The ID of the wallet the address belongs to.
# @param address_id [String] The onchain address of the address that is being fetched.
# @param [Hash] opts the optional parameters
# @return [Array<(FaucetTransaction, Integer, Hash)>] FaucetTransaction data, response status code and response headers
def request_faucet_funds_with_http_info(wallet_id, address_id, opts = {})
if @api_client.config.debugging
@api_client.config.logger.debug 'Calling API: AddressesApi.request_faucet_funds ...'
end
# verify the required parameter 'wallet_id' is set
if @api_client.config.client_side_validation && wallet_id.nil?
fail ArgumentError, "Missing the required parameter 'wallet_id' when calling AddressesApi.request_faucet_funds"
end
# verify the required parameter 'address_id' is set
if @api_client.config.client_side_validation && address_id.nil?
fail ArgumentError, "Missing the required parameter 'address_id' when calling AddressesApi.request_faucet_funds"
end
# resource path
local_var_path = '/v1/wallets/{wallet_id}/addresses/{address_id}/faucet'.sub('{' + 'wallet_id' + '}', CGI.escape(wallet_id.to_s)).sub('{' + 'address_id' + '}', CGI.escape(address_id.to_s))

# query parameters
query_params = opts[:query_params] || {}

# header parameters
header_params = opts[:header_params] || {}
# HTTP header 'Accept' (if needed)
header_params['Accept'] = @api_client.select_header_accept(['application/json'])

# form parameters
form_params = opts[:form_params] || {}

# http body (model)
post_body = opts[:debug_body]

# return_type
return_type = opts[:debug_return_type] || 'FaucetTransaction'

# auth_names
auth_names = opts[:debug_auth_names] || []

new_options = opts.merge(
:operation => :"AddressesApi.request_faucet_funds",
:header_params => header_params,
:query_params => query_params,
:form_params => form_params,
:body => post_body,
:auth_names => auth_names,
:return_type => return_type
)

data, status_code, headers = @api_client.call_api(:POST, local_var_path, new_options)
if @api_client.config.debugging
@api_client.config.logger.debug "API called: AddressesApi#request_faucet_funds\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
end
return data, status_code, headers
end
end
end
222 changes: 222 additions & 0 deletions lib/coinbase/client/models/faucet_transaction.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
=begin
#Coinbase Platform API

#This is the OpenAPI 3.0 specification for the Coinbase Platform APIs, used in conjunction with the Coinbase Platform SDKs.

The version of the OpenAPI document: 0.0.1-alpha
Contact: [email protected]
Generated by: https://openapi-generator.tech
Generator version: 7.5.0

=end

require 'date'
require 'time'

module Coinbase::Client
class FaucetTransaction
# The transaction hash of the transaction the faucet created.
attr_accessor :transaction_hash

# Attribute mapping from ruby-style variable name to JSON key.
def self.attribute_map
{
:'transaction_hash' => :'transaction_hash'
}
end

# Returns all the JSON keys this model knows about
def self.acceptable_attributes
attribute_map.values
end

# Attribute type mapping.
def self.openapi_types
{
:'transaction_hash' => :'String'
}
end

# List of attributes with nullable: true
def self.openapi_nullable
Set.new([
])
end

# Initializes the object
# @param [Hash] attributes Model attributes in the form of hash
def initialize(attributes = {})
if (!attributes.is_a?(Hash))
fail ArgumentError, "The input argument (attributes) must be a hash in `Coinbase::Client::FaucetTransaction` initialize method"
end

# check to see if the attribute exists and convert string to symbol for hash key
attributes = attributes.each_with_object({}) { |(k, v), h|
if (!self.class.attribute_map.key?(k.to_sym))
fail ArgumentError, "`#{k}` is not a valid attribute in `Coinbase::Client::FaucetTransaction`. Please check the name to make sure it's valid. List of attributes: " + self.class.attribute_map.keys.inspect
end
h[k.to_sym] = v
}

if attributes.key?(:'transaction_hash')
self.transaction_hash = attributes[:'transaction_hash']
else
self.transaction_hash = nil
end
end

# Show invalid properties with the reasons. Usually used together with valid?
# @return Array for valid properties with the reasons
def list_invalid_properties
warn '[DEPRECATED] the `list_invalid_properties` method is obsolete'
invalid_properties = Array.new
if @transaction_hash.nil?
invalid_properties.push('invalid value for "transaction_hash", transaction_hash cannot be nil.')
end

invalid_properties
end

# Check to see if the all the properties in the model are valid
# @return true if the model is valid
def valid?
warn '[DEPRECATED] the `valid?` method is obsolete'
return false if @transaction_hash.nil?
true
end

# Checks equality by comparing each attribute.
# @param [Object] Object to be compared
def ==(o)
return true if self.equal?(o)
self.class == o.class &&
transaction_hash == o.transaction_hash
end

# @see the `==` method
# @param [Object] Object to be compared
def eql?(o)
self == o
end

# Calculates hash code according to all attributes.
# @return [Integer] Hash code
def hash
[transaction_hash].hash
end

# Builds the object from hash
# @param [Hash] attributes Model attributes in the form of hash
# @return [Object] Returns the model itself
def self.build_from_hash(attributes)
return nil unless attributes.is_a?(Hash)
attributes = attributes.transform_keys(&:to_sym)
transformed_hash = {}
openapi_types.each_pair do |key, type|
if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil?
transformed_hash["#{key}"] = nil
elsif type =~ /\AArray<(.*)>/i
# check to ensure the input is an array given that the attribute
# is documented as an array but the input is not
if attributes[attribute_map[key]].is_a?(Array)
transformed_hash["#{key}"] = attributes[attribute_map[key]].map { |v| _deserialize($1, v) }
end
elsif !attributes[attribute_map[key]].nil?
transformed_hash["#{key}"] = _deserialize(type, attributes[attribute_map[key]])
end
end
new(transformed_hash)
end

# Deserializes the data based on type
# @param string type Data type
# @param string value Value to be deserialized
# @return [Object] Deserialized data
def self._deserialize(type, value)
case type.to_sym
when :Time
Time.parse(value)
when :Date
Date.parse(value)
when :String
value.to_s
when :Integer
value.to_i
when :Float
value.to_f
when :Boolean
if value.to_s =~ /\A(true|t|yes|y|1)\z/i
true
else
false
end
when :Object
# generic object (usually a Hash), return directly
value
when /\AArray<(?<inner_type>.+)>\z/
inner_type = Regexp.last_match[:inner_type]
value.map { |v| _deserialize(inner_type, v) }
when /\AHash<(?<k_type>.+?), (?<v_type>.+)>\z/
k_type = Regexp.last_match[:k_type]
v_type = Regexp.last_match[:v_type]
{}.tap do |hash|
value.each do |k, v|
hash[_deserialize(k_type, k)] = _deserialize(v_type, v)
end
end
else # model
# models (e.g. Pet) or oneOf
klass = Coinbase::Client.const_get(type)
klass.respond_to?(:openapi_any_of) || klass.respond_to?(:openapi_one_of) ? klass.build(value) : klass.build_from_hash(value)
end
end

# Returns the string representation of the object
# @return [String] String presentation of the object
def to_s
to_hash.to_s
end

# to_body is an alias to to_hash (backward compatibility)
# @return [Hash] Returns the object in the form of hash
def to_body
to_hash
end

# Returns the object in the form of hash
# @return [Hash] Returns the object in the form of hash
def to_hash
hash = {}
self.class.attribute_map.each_pair do |attr, param|
value = self.send(attr)
if value.nil?
is_nullable = self.class.openapi_nullable.include?(attr)
next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}"))
end

hash[param] = _to_hash(value)
end
hash
end

# Outputs non-array value in the form of hash
# For object, use to_hash. Otherwise, just return the value
# @param [Object] value Any valid value
# @return [Hash] Returns the value in the form of hash
def _to_hash(value)
if value.is_a?(Array)
value.compact.map { |v| _to_hash(v) }
elsif value.is_a?(Hash)
{}.tap do |hash|
value.each { |k, v| hash[k] = _to_hash(v) }
end
elsif value.respond_to? :to_hash
value.to_hash
else
value
end
end

end

end
21 changes: 21 additions & 0 deletions lib/coinbase/faucet_transaction.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# frozen_string_literal: true

module Coinbase
# A representation of a transaction from a faucet.
# a user-controlled Wallet to another address. The fee is assumed to be paid
# in the native Asset of the Network. Transfers should be created through Wallet#transfer or
# Address#transfer.
class FaucetTransaction
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These can be follow-ups but:

  1. Yardocs
  2. Can we addwait! and status functions as we do with Transfer. Possibly an opportunity to factor out an class or module that has those methods

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added docs fro this class.

The wait! and status functions could be added, but this transaction is only returned after it lands on-chain.

def initialize(model)
@model = model
end

attr_reader :model

# Returns the transaction hash.
# @return [String] The onchain transaction hash
def transaction_hash
model.transaction_hash
end
end
end
Loading
Loading