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.31.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
- TOKEN_FIELDS =
Fields read by Sdp::Token.from_hash. extensions is passed through untyped.
%w[id projectId signingWalletId mintAddress mintAuthority freezeAuthority name symbol decimals description uri imageUrl template extensions totalSupply maxSupply isMintable isFreezable requiresAllowlist status deployedAt createdAt updatedAt].freeze
- TOKEN_TX_FIELDS =
Fields read by Sdp::TokenTransaction.from_hash (the mint/burn action record).
%w[id tokenId type status signature serializedTx params slot blockTime fee error createdAt updatedAt].freeze
- PREPARED_TX_FIELDS =
The unsigned-transaction envelope shared by the …/prepare responses.
%w[serialized blockhash lastValidBlockHeight].freeze
- RAMP_QUOTE_FIELDS =
Fields read by Sdp::RampQuote.from_hash. The *Currency members are passed through untyped, so only their presence at data.quote is pinned.
%w[id provider status deliveryMode hostedUrl paymentInstructions exchangeRate totalSendingAmount sendingCurrency totalReceivingAmount receivingCurrency feesIncluded feeCurrency expiresAt].freeze
- RAMP_EXECUTION_FIELDS =
Fields read by Sdp::RampExecution.from_hash.
%w[id provider status redirectUrl paymentInstructions reference].freeze
- COVERED_ENDPOINTS =
[ # NOTE: at v0.31 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 }), # Issuance — token lifecycle + supply actions (v0.2). list returns a bare # data array; create/get/deploy wrap the token in data.token. mint/burn # return the action record at data.transaction; mint also carries # data.tokenAccount. The prepare variants differ: deploy/prepare puts the # unsigned tx at data.transaction with a sibling data.mint, while # mint/burn prepare keep the record at data.transaction and the unsigned # tx at data.preparedTransaction. Endpoint.new(method: "get", path: "/v1/issuance/tokens", success_status: "200", reads: { [ "data", "[]" ] => TOKEN_FIELDS }), Endpoint.new(method: "post", path: "/v1/issuance/tokens", success_status: "201", reads: { %w[data token] => TOKEN_FIELDS }), Endpoint.new(method: "get", path: "/v1/issuance/tokens/{tokenId}", success_status: "200", reads: { %w[data token] => TOKEN_FIELDS }), Endpoint.new(method: "post", path: "/v1/issuance/tokens/{tokenId}/deploy", success_status: "200", reads: { %w[data token] => TOKEN_FIELDS }), Endpoint.new(method: "post", path: "/v1/issuance/tokens/{tokenId}/deploy/prepare", success_status: "200", reads: { %w[data] => %w[transaction mint simulation], %w[data transaction] => PREPARED_TX_FIELDS }), Endpoint.new(method: "post", path: "/v1/issuance/tokens/{tokenId}/mint", success_status: "200", reads: { %w[data] => %w[transaction tokenAccount], %w[data transaction] => TOKEN_TX_FIELDS }), Endpoint.new(method: "post", path: "/v1/issuance/tokens/{tokenId}/mint/prepare", success_status: "200", reads: { %w[data] => %w[transaction preparedTransaction tokenAccount simulation], %w[data transaction] => TOKEN_TX_FIELDS, %w[data preparedTransaction] => PREPARED_TX_FIELDS }), Endpoint.new(method: "post", path: "/v1/issuance/tokens/{tokenId}/burn", success_status: "200", reads: { %w[data transaction] => TOKEN_TX_FIELDS }), Endpoint.new(method: "post", path: "/v1/issuance/tokens/{tokenId}/burn/prepare", success_status: "200", reads: { %w[data] => %w[transaction preparedTransaction simulation], %w[data transaction] => TOKEN_TX_FIELDS, %w[data preparedTransaction] => PREPARED_TX_FIELDS }), # Ramps (v0.2, sandbox-only). currency endpoints return nested discovery # data; quote wraps the record in data.quote, execute in data.ramp; the # sandbox hook returns data.transaction (untyped passthrough). Endpoint.new(method: "get", path: "/v1/payments/ramps/onramp/currency", success_status: "200", reads: { %w[data] => %w[currencies pairs supportHash], %w[data currencies] => %w[sources destinations], [ "data", "pairs", "[]" ] => %w[source dest providers] }), Endpoint.new(method: "get", path: "/v1/payments/ramps/offramp/currency", success_status: "200", reads: { %w[data] => %w[currencies pairs supportHash], %w[data currencies] => %w[sources destinations], [ "data", "pairs", "[]" ] => %w[source dest providers] }), Endpoint.new(method: "post", path: "/v1/payments/ramps/onramp/quote", success_status: "200", reads: { %w[data quote] => RAMP_QUOTE_FIELDS }), Endpoint.new(method: "post", path: "/v1/payments/ramps/onramp/execute", success_status: "200", reads: { %w[data ramp] => RAMP_EXECUTION_FIELDS }), Endpoint.new(method: "post", path: "/v1/payments/ramps/offramp/execute", success_status: "200", reads: { %w[data ramp] => RAMP_EXECUTION_FIELDS }), Endpoint.new(method: "post", path: "/v1/payments/ramps/sandbox/simulate", success_status: "200", reads: { %w[data] => %w[transaction] }) ].freeze
Class Method Summary collapse
-
.resolve(spec, node, depth = 0) ⇒ Object
Follows “$ref”: “#/components/schemas/X” pointers (recursively, with a depth guard).
-
.success_schema(spec, endpoint) ⇒ Object
The application/json schema of the endpoint’s documented success response, $ref-resolved.
-
.walk(spec, schema, segments) ⇒ Object
Navigates a (resolved) schema along a reads path.
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.31) — this keeps the guard working if that changes.
141 142 143 144 145 146 147 148 149 |
# File 'lib/sdp/coverage.rb', line 141 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.
120 121 122 123 124 |
# File 'lib/sdp/coverage.rb', line 120 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.
129 130 131 132 133 134 135 136 |
# File 'lib/sdp/coverage.rb', line 129 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 |