Architecture Guide
View SourceThis page describes the low-level workflow of the BinanceSpotRest
library.
Intended for advanced users, contributors, or testing purposes.
1. Query Structs
Every endpoint is represented by a query struct, e.g.:
%BinanceSpotRest.Endpoints.General.Time.Query{}
These structs may have parameters depending on the endpoint. They are the starting point for building requests.
2. Validation
Before sending, a query should be validated using the BinanceSpotRest.Query
protocol:
import Loe
query = %BinanceSpotRest.Endpoints.General.Time.Query{}
{:ok, validated_query} = query ~>> BinanceSpotRest.Query.validate()
- Returns
{:ok, query}
if valid - Returns
{:error, reason}
if invalid
3. Preparation
Prepare the query for execution using prepare/1
:
{:ok, request_spec} = validated_query ~>> BinanceSpotRest.Query.prepare()
- Produces a
%BinanceSpotRest.Query.RequestSpec{}
struct containing:metadata
→%BinanceSpotRest.Query.EndpointMetadata{}
endpoint
— API path (string)method
— HTTP method (:get
,:post
, etc.)security_type
— endpoint security (:NONE
,:TRADE
, etc.)
query
→ original query struct
4. Build Request
Turn the RequestSpec
into a client request using BinanceSpotRest.Client.create_request/2
:
request = BinanceSpotRest.Client.create_request(request_spec)
- Produces
%BinanceSpotRest.Client.Request{}
- Accepts optional overrides for testing or mocking:
request = BinanceSpotRest.Client.create_request(request_spec,
base_url: "https://mock.url",
headers: [{"FAKE_API_KEY", "fake_api_key"}],
timestamp_fn: fn -> 1_740_000_000_000 end,
signature_fn: fn _qs, _key -> "mock-signature" end
)
5. Make Request
Execute the built client request using make_request/1
:
{:ok, response} = BinanceSpotRest.Client.make_request(request)
- Sends the request via
Req
- Returns
{:ok, response}
or{:error, reason}
Workflow Diagram
┌───────────────────────────────┐
│ Query Struct │
│ %BinanceSpotRest.Endpoints.* │
└──────────────┬────────────────┘
│ validate()
▼
┌───────────────────────────────┐
│ Validated Query Struct │
└──────────────┬────────────────┘
│ prepare()
▼
┌────────────────────────────────────────────┐
│ RequestSpec Struct │
│ %BinanceSpotRest.Query.RequestSpec │
│ metadata + original query │
└────────────────────┬───────────────────────┘
│ create_request(opts \\ [])
▼
┌──────────────────────────────────┐
│ Client Request Struct │
│ %BinanceSpotRest.Client.Request │
└───────────────┬──────────────────┘
│ make_request()
▼
┌───────────────────────────┐
│ HTTP Response │
└───────────────────────────┘
Pipeline
For convenience, the entire flow can be expressed as a pipeline using Loe
.
(The diagram above shows the step-by-step flow; the pipeline below demonstrates the same process in practice.)
import Loe
%BinanceSpotRest.Endpoints.General.Time.Query{}
~>> BinanceSpotRest.Query.validate()
~>> BinanceSpotRest.Query.prepare()
~>> BinanceSpotRest.Client.create_request()
~>> BinanceSpotRest.Client.make_request()
# => {:ok, response} or {:error, reason}
Notes
- This workflow is optional; for most use cases, simply call:
{:ok, result} = BinanceSpotRest.request(query)
- Internal modules like
RequestSpec
,EndpointMetadata
,Client.Timestamp
, andClient.Signature
are used automatically. - Direct low-level use is intended for testing, mocking, or advanced contributions.