Class: Sdp::Client
- Inherits:
-
Object
- Object
- Sdp::Client
- Includes:
- Resources::Payments, Resources::Wallets
- Defined in:
- lib/sdp/client.rb
Overview
Zero-dependency Net::HTTP request core for the SDP API.
Success envelope: { “data”: …, “meta”: … } Error envelope: { “error”: { “code”, “message”, “details” }, “meta”: … }
Retry policy: GETs retry once on Timeout/Unavailable. POSTs NEVER retry —SDP has no idempotency key, so re-sending a transfer risks a double-spend.
Endpoint methods live in resource modules layered on top of the #get/#post primitives below; this class owns auth, envelope handling, the typed error mapping, and the retry posture.
Defined Under Namespace
Classes: Response
Constant Summary collapse
- DEFAULT_BASE_URL =
"http://127.0.0.1:8787"- OPEN_TIMEOUT =
seconds — fail fast when the stack isn’t up
2- READ_TIMEOUT =
seconds — transfer confirmation is synchronous
10- NOT_FOUND_HINT =
Wallet-scoped API keys return 404 (not 403) for wallets outside their scope, which reads like “does not exist” when it really means “not yours”. Appended to every NotFound so the failure is diagnosable.
"(hint: wallet-scoped API keys return 404 for wallets outside their scope)"
Instance Attribute Summary collapse
-
#base_url ⇒ Object
readonly
Returns the value of attribute base_url.
Instance Method Summary collapse
-
#get(path, query: nil) ⇒ Object
Reads are safe to retry exactly once on transport-level failures.
-
#initialize(base_url: ENV.fetch("SDP_API_BASE_URL", DEFAULT_BASE_URL), api_key: ENV["SDP_API_KEY"], open_timeout: OPEN_TIMEOUT, read_timeout: READ_TIMEOUT) ⇒ Client
constructor
A new instance of Client.
-
#inspect ⇒ Object
Redacted on purpose: the API key is a bearer secret and must never leak into consoles, logs, or exception-capture payloads via the default #inspect (which would dump every instance variable, @api_key included).
- #post(path, payload = nil) ⇒ Object
Methods included from Resources::Payments
#create_transfer, #get_transfer, #list_transfers, #prepare_transfer
Methods included from Resources::Wallets
#create_wallet, #initialize_custody, #list_wallets, #wallet_balances
Constructor Details
#initialize(base_url: ENV.fetch("SDP_API_BASE_URL", DEFAULT_BASE_URL), api_key: ENV["SDP_API_KEY"], open_timeout: OPEN_TIMEOUT, read_timeout: READ_TIMEOUT) ⇒ Client
Returns a new instance of Client.
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/sdp/client.rb', line 45 def initialize(base_url: ENV.fetch("SDP_API_BASE_URL", DEFAULT_BASE_URL), api_key: ENV["SDP_API_KEY"], open_timeout: OPEN_TIMEOUT, read_timeout: READ_TIMEOUT) # Strip first, then guard: an ENV key with a trailing newline passes a # naive blank-check but then makes every request raise a raw ArgumentError # from the "Bearer …\n" header. Normalize once, at the boundary. @api_key = api_key.to_s.strip if @api_key.empty? raise ConfigurationError, "SDP_API_KEY is missing or blank. " \ "Pass api_key: or set the SDP_API_KEY environment variable." end @base_url = base_url.to_s.chomp("/") # base_url is documented as ConfigurationError-covered, so validate it at # boot (mirroring the api_key fail-fast) instead of letting an unusable # URL surface as a cryptic transport error on the first request. parsed = begin URI.parse(@base_url) rescue URI::InvalidURIError nil end unless parsed.is_a?(URI::HTTP) && !parsed.host.to_s.empty? raise ConfigurationError, "SDP_API_BASE_URL is invalid: expected an http(s) URL with a " \ "host, got #{@base_url.inspect}. Pass base_url: or set the SDP_API_BASE_URL environment variable." end @open_timeout = open_timeout @read_timeout = read_timeout end |
Instance Attribute Details
#base_url ⇒ Object (readonly)
Returns the value of attribute base_url.
43 44 45 |
# File 'lib/sdp/client.rb', line 43 def base_url @base_url end |
Instance Method Details
#get(path, query: nil) ⇒ Object
Reads are safe to retry exactly once on transport-level failures.
88 89 90 91 92 93 |
# File 'lib/sdp/client.rb', line 88 def get(path, query: nil) uri = build_uri(path, query) with_read_retry do perform(Net::HTTP::Get.new(uri), uri, idempotent: true) end end |
#inspect ⇒ Object
Redacted on purpose: the API key is a bearer secret and must never leak into consoles, logs, or exception-capture payloads via the default #inspect (which would dump every instance variable, @api_key included).
79 80 81 |
# File 'lib/sdp/client.rb', line 79 def inspect "#<#{self.class} base_url=#{@base_url.inspect}>" end |
#post(path, payload = nil) ⇒ Object
95 96 97 98 99 100 101 |
# File 'lib/sdp/client.rb', line 95 def post(path, payload = nil) uri = build_uri(path, nil) request = Net::HTTP::Post.new(uri) request["Content-Type"] = "application/json" request.body = JSON.generate(payload) unless payload.nil? perform(request, uri, idempotent: false) # no retry wrapper — writes are never retried end |