diff --git a/sdk/lib/stellar-sdk.rb b/sdk/lib/stellar-sdk.rb index 7782c844..f1975ff7 100644 --- a/sdk/lib/stellar-sdk.rb +++ b/sdk/lib/stellar-sdk.rb @@ -6,6 +6,7 @@ module Stellar autoload :Amount autoload :Client autoload :SEP10 + autoload :HorizonError module Horizon extend ActiveSupport::Autoload diff --git a/sdk/lib/stellar/client.rb b/sdk/lib/stellar/client.rb index 93da8908..9ff188e8 100644 --- a/sdk/lib/stellar/client.rb +++ b/sdk/lib/stellar/client.rb @@ -200,6 +200,9 @@ def submit_transaction(tx_envelope:, options: {skip_memo_required_check: false}) check_memo_required(tx_envelope) end @horizon.transactions._post(tx: tx_envelope.to_xdr(:base64)) + + rescue Faraday::BadRequestError => ex + raise HorizonError.make(ex.response[:body]) end # Required by SEP-0029 diff --git a/sdk/lib/stellar/horizon_error.rb b/sdk/lib/stellar/horizon_error.rb new file mode 100644 index 00000000..7a0bd845 --- /dev/null +++ b/sdk/lib/stellar/horizon_error.rb @@ -0,0 +1,53 @@ +module Stellar + class HorizonError < StandardError + attr_reader :original_response, :extras + + def self.make(original_response) + klass = class_for(original_response["title"]) + klass.new(original_response) + end + + # Uses specialized class if it is defined + def self.class_for(title) + const_get title.delete(" ").to_sym + rescue NameError + self + end + + def initialize(original_response) + message = make_message( + detail: original_response["detail"], + title: original_response["title"] + ) + + # Superclass StandardError has different argument signature + super(message) + + @original_response = original_response + @extras = original_response["extras"] + end + + private + + def make_message(detail:, title:) + # Include title only on generic class + # Condition passes only for child classes + if self.class != HorizonError + title = nil + end + + [title, detail].compact.join(": ") + end + + class TransactionFailed < self + def make_message(detail:) + detail.sub!( + "The `extras.result_codes` field on this response contains further details.", + "extras.result_codes contained: `#{hash.dig("extras", "result_codes")}`" + ) + end + end + + class TransactionMalformed < self; end + end +end