Module: Sdp::Coverage

Defined in:
lib/sdp/coverage.rb

Overview

The curated SDP surface this gem covers, pinned against the vendored OpenAPI spec (spec/openapi-v0.28.json). Consumed by the contract tests (test/sdp/contract_test.rb) and the sdp:drift rake task.

Path templates use the param style of SDP’s generated spec. When a resource method is added or removed, this map changes in the same commit.

Defined Under Namespace

Classes: Endpoint

Constant Summary collapse

WALLET_FIELDS =

Fields read by Sdp::Wallet.from_hash.

%w[id walletId publicKey label status provider purpose createdAt balances].freeze
BALANCE_FIELDS =

Fields read by Sdp::Balance.from_hash. usdValue is optional upstream —presence in the schema’s properties is what we pin, not requiredness.

%w[token mint amount uiAmount decimals usdValue].freeze
TRANSFER_FIELDS =

Fields read by Sdp::Transfer.from_hash.

%w[id direction status signature token amount source destination memo error createdAt].freeze
COVERED_ENDPOINTS =
[
  # NOTE: at v0.28 the initialize 201 response has NO data envelope —
  # configId/publicKey/walletId sit at the schema root.
  Endpoint.new(method: "post", path: "/v1/wallets/initialize", success_status: "201",
               reads: { [] => %w[configId publicKey walletId] }),
  Endpoint.new(method: "post", path: "/v1/wallets", success_status: "201",
               reads: { %w[data wallet] => WALLET_FIELDS }),
  Endpoint.new(method: "get", path: "/v1/wallets", success_status: "200",
               reads: { [ "data", "wallets", "[]" ] => WALLET_FIELDS }),
  Endpoint.new(method: "get", path: "/v1/payments/wallets/{walletId}/balances", success_status: "200",
               reads: { %w[data walletBalances] => %w[walletId balances],
                        [ "data", "walletBalances", "balances", "[]" ] => BALANCE_FIELDS }),
  Endpoint.new(method: "post", path: "/v1/payments/transfers", success_status: "200",
               reads: { %w[data transfer] => TRANSFER_FIELDS }),
  Endpoint.new(method: "post", path: "/v1/payments/transfers/prepare", success_status: "200",
               reads: { %w[data] => %w[transfer preparedTransaction simulation],
                        %w[data transfer] => TRANSFER_FIELDS,
                        %w[data preparedTransaction] => %w[serialized blockhash lastValidBlockHeight] }),
  Endpoint.new(method: "get", path: "/v1/payments/transfers", success_status: "200",
               reads: { [ "data", "[]" ] => TRANSFER_FIELDS }),
  Endpoint.new(method: "get", path: "/v1/payments/transfers/{transferId}", success_status: "200",
               reads: { %w[data transfer] => TRANSFER_FIELDS })
].freeze

Class Method Summary collapse

Class Method Details

.resolve(spec, node, depth = 0) ⇒ Object

Follows “$ref”: “#/components/schemas/X” pointers (recursively, with a depth guard). SDP’s generated spec is fully inlined today (zero $refs at v0.28) — this keeps the guard working if that changes.



73
74
75
76
77
78
79
80
81
# File 'lib/sdp/coverage.rb', line 73

def resolve(spec, node, depth = 0)
  return node unless node.is_a?(Hash) && node["$ref"].is_a?(String)
  return nil if depth > 10

  name = node["$ref"][%r{\A#/components/schemas/(.+)\z}, 1]
  return nil unless name

  resolve(spec, spec.dig("components", "schemas", name), depth + 1)
end

.success_schema(spec, endpoint) ⇒ Object

The application/json schema of the endpoint’s documented success response, $ref-resolved. nil when the spec doesn’t document it.



52
53
54
55
56
# File 'lib/sdp/coverage.rb', line 52

def success_schema(spec, endpoint)
  operation = spec.dig("paths", endpoint.path, endpoint.method)
  schema = operation&.dig("responses", endpoint.success_status, "content", "application/json", "schema")
  resolve(spec, schema)
end

.walk(spec, schema, segments) ⇒ Object

Navigates a (resolved) schema along a reads path. “[]” descends into array items; any other segment descends into that property. Returns the resolved node, or nil as soon as the path breaks.



61
62
63
64
65
66
67
68
# File 'lib/sdp/coverage.rb', line 61

def walk(spec, schema, segments)
  segments.reduce(resolve(spec, schema)) do |node, segment|
    break nil unless node

    child = segment == "[]" ? node["items"] : node.dig("properties", segment)
    resolve(spec, child)
  end
end