Current section
Files
Jump to
Current section
Files
src/glupbit@websocket@subscription.erl
-module(glupbit@websocket@subscription).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/glupbit/websocket/subscription.gleam").
-export([build_list_subscriptions_message/1, build_subscription_message/3, ticker_data_decoder/0, trade_data_decoder/0, orderbook_data_decoder/0, subscription_info_decoder/0, list_subscriptions_response_decoder/0]).
-export_type([ws_format/0, subscription/0, ticker_data/0, trade_data/0, orderbook_data/0, subscription_info/0, list_subscriptions_response/0]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(" WebSocket subscription types, message builders, and response decoders.\n").
-type ws_format() :: default | simple | json_list | simple_list.
-type subscription() :: {ticker_sub,
list(glupbit@types:market()),
boolean(),
boolean()} |
{trade_sub, list(glupbit@types:market()), boolean(), boolean()} |
{orderbook_sub,
list(glupbit@types:market()),
gleam@option:option(binary()),
boolean(),
boolean()} |
{candle_sub, list(glupbit@types:market()), binary(), boolean(), boolean()} |
{my_order_sub, gleam@option:option(list(glupbit@types:market()))} |
my_asset_sub.
-type ticker_data() :: {ticker_data,
binary(),
float(),
binary(),
float(),
float(),
integer()}.
-type trade_data() :: {trade_data,
binary(),
float(),
float(),
binary(),
integer(),
integer()}.
-type orderbook_data() :: {orderbook_data,
binary(),
float(),
float(),
list(glupbit@quotation@orderbook:orderbook_unit()),
integer()}.
-type subscription_info() :: {subscription_info,
binary(),
gleam@option:option(list(binary())),
gleam@option:option(float())}.
-type list_subscriptions_response() :: {list_subscriptions_response,
binary(),
list(subscription_info()),
binary()}.
-file("src/glupbit/websocket/subscription.gleam", 64).
?DOC(" Build a LIST_SUBSCRIPTIONS request message as a JSON string.\n").
-spec build_list_subscriptions_message(binary()) -> binary().
build_list_subscriptions_message(Ticket) ->
Ticket_obj = gleam@json:object(
[{<<"ticket"/utf8>>, gleam@json:string(Ticket)}]
),
Method_obj = gleam@json:object(
[{<<"method"/utf8>>, gleam@json:string(<<"LIST_SUBSCRIPTIONS"/utf8>>)}]
),
gleam@json:to_string(
gleam@json:preprocessed_array([Ticket_obj, Method_obj])
).
-file("src/glupbit/websocket/subscription.gleam", 70).
-spec ws_format_to_string(ws_format()) -> binary().
ws_format_to_string(Format) ->
case Format of
default ->
<<"DEFAULT"/utf8>>;
simple ->
<<"SIMPLE"/utf8>>;
json_list ->
<<"JSON_LIST"/utf8>>;
simple_list ->
<<"SIMPLE_LIST"/utf8>>
end.
-file("src/glupbit/websocket/subscription.gleam", 135).
-spec build_sub_json(
binary(),
list(glupbit@types:market()),
gleam@option:option(binary()),
gleam@option:option(binary()),
boolean(),
boolean()
) -> gleam@json:json().
build_sub_json(Type_name, Codes, Level, _, Is_only_snapshot, Is_only_realtime) ->
Fields = [{<<"type"/utf8>>, gleam@json:string(Type_name)},
{<<"codes"/utf8>>,
gleam@json:array(
Codes,
fun(M) ->
gleam@json:string(glupbit@types:market_to_string(M))
end
)}],
Fields@1 = case Level of
{some, L} ->
[{<<"level"/utf8>>, gleam@json:string(L)} | Fields];
none ->
Fields
end,
Fields@2 = case Is_only_snapshot of
true ->
[{<<"isOnlySnapshot"/utf8>>, gleam@json:bool(true)} | Fields@1];
false ->
Fields@1
end,
Fields@3 = case Is_only_realtime of
true ->
[{<<"isOnlyRealtime"/utf8>>, gleam@json:bool(true)} | Fields@2];
false ->
Fields@2
end,
gleam@json:object(Fields@3).
-file("src/glupbit/websocket/subscription.gleam", 79).
-spec subscription_to_json(subscription()) -> gleam@json:json().
subscription_to_json(Sub) ->
case Sub of
{ticker_sub, Codes, Is_only_snapshot, Is_only_realtime} ->
build_sub_json(
<<"ticker"/utf8>>,
Codes,
none,
none,
Is_only_snapshot,
Is_only_realtime
);
{trade_sub, Codes@1, Is_only_snapshot@1, Is_only_realtime@1} ->
build_sub_json(
<<"trade"/utf8>>,
Codes@1,
none,
none,
Is_only_snapshot@1,
Is_only_realtime@1
);
{orderbook_sub, Codes@2, Level, Is_only_snapshot@2, Is_only_realtime@2} ->
build_sub_json(
<<"orderbook"/utf8>>,
Codes@2,
Level,
none,
Is_only_snapshot@2,
Is_only_realtime@2
);
{candle_sub, Codes@3, Unit, Is_only_snapshot@3, Is_only_realtime@3} ->
build_sub_json(
<<"candle."/utf8, Unit/binary>>,
Codes@3,
none,
none,
Is_only_snapshot@3,
Is_only_realtime@3
);
{my_order_sub, Codes@4} ->
Base = [{<<"type"/utf8>>, gleam@json:string(<<"myOrder"/utf8>>)}],
Fields = case Codes@4 of
{some, C} ->
[{<<"codes"/utf8>>,
gleam@json:array(
C,
fun(M) ->
gleam@json:string(
glupbit@types:market_to_string(M)
)
end
)} |
Base];
none ->
Base
end,
gleam@json:object(Fields);
my_asset_sub ->
gleam@json:object(
[{<<"type"/utf8>>, gleam@json:string(<<"myAsset"/utf8>>)}]
)
end.
-file("src/glupbit/websocket/subscription.gleam", 50).
?DOC(
" Build a WebSocket subscription message as a JSON string.\n"
" Returns a JSON array: [{\"ticket\":\"...\"}, {\"type\":\"ticker\",\"codes\":[...]}, ..., {\"format\":\"DEFAULT\"}]\n"
).
-spec build_subscription_message(binary(), list(subscription()), ws_format()) -> binary().
build_subscription_message(Ticket, Subscriptions, Format) ->
Ticket_obj = gleam@json:object(
[{<<"ticket"/utf8>>, gleam@json:string(Ticket)}]
),
Sub_objs = gleam@list:map(Subscriptions, fun subscription_to_json/1),
Format_obj = gleam@json:object(
[{<<"format"/utf8>>, gleam@json:string(ws_format_to_string(Format))}]
),
All = [Ticket_obj | lists:append(Sub_objs, [Format_obj])],
gleam@json:to_string(gleam@json:preprocessed_array(All)).
-file("src/glupbit/websocket/subscription.gleam", 205).
?DOC(" Decoder for WebSocket ticker data.\n").
-spec ticker_data_decoder() -> gleam@dynamic@decode:decoder(ticker_data()).
ticker_data_decoder() ->
gleam@dynamic@decode:field(
<<"code"/utf8>>,
{decoder, fun gleam@dynamic@decode:decode_string/1},
fun(Code) ->
gleam@dynamic@decode:field(
<<"trade_price"/utf8>>,
{decoder, fun gleam@dynamic@decode:decode_float/1},
fun(Trade_price) ->
gleam@dynamic@decode:field(
<<"change"/utf8>>,
{decoder, fun gleam@dynamic@decode:decode_string/1},
fun(Change) ->
gleam@dynamic@decode:field(
<<"signed_change_rate"/utf8>>,
{decoder,
fun gleam@dynamic@decode:decode_float/1},
fun(Signed_change_rate) ->
gleam@dynamic@decode:field(
<<"acc_trade_volume_24h"/utf8>>,
{decoder,
fun gleam@dynamic@decode:decode_float/1},
fun(Acc_trade_volume_24h) ->
gleam@dynamic@decode:field(
<<"timestamp"/utf8>>,
{decoder,
fun gleam@dynamic@decode:decode_int/1},
fun(Timestamp) ->
gleam@dynamic@decode:success(
{ticker_data,
Code,
Trade_price,
Change,
Signed_change_rate,
Acc_trade_volume_24h,
Timestamp}
)
end
)
end
)
end
)
end
)
end
)
end
).
-file("src/glupbit/websocket/subscription.gleam", 223).
?DOC(" Decoder for WebSocket trade data.\n").
-spec trade_data_decoder() -> gleam@dynamic@decode:decoder(trade_data()).
trade_data_decoder() ->
gleam@dynamic@decode:field(
<<"code"/utf8>>,
{decoder, fun gleam@dynamic@decode:decode_string/1},
fun(Code) ->
gleam@dynamic@decode:field(
<<"trade_price"/utf8>>,
{decoder, fun gleam@dynamic@decode:decode_float/1},
fun(Trade_price) ->
gleam@dynamic@decode:field(
<<"trade_volume"/utf8>>,
{decoder, fun gleam@dynamic@decode:decode_float/1},
fun(Trade_volume) ->
gleam@dynamic@decode:field(
<<"ask_bid"/utf8>>,
{decoder,
fun gleam@dynamic@decode:decode_string/1},
fun(Ask_bid) ->
gleam@dynamic@decode:field(
<<"trade_timestamp"/utf8>>,
{decoder,
fun gleam@dynamic@decode:decode_int/1},
fun(Trade_timestamp) ->
gleam@dynamic@decode:field(
<<"sequential_id"/utf8>>,
{decoder,
fun gleam@dynamic@decode:decode_int/1},
fun(Sequential_id) ->
gleam@dynamic@decode:success(
{trade_data,
Code,
Trade_price,
Trade_volume,
Ask_bid,
Trade_timestamp,
Sequential_id}
)
end
)
end
)
end
)
end
)
end
)
end
).
-file("src/glupbit/websocket/subscription.gleam", 241).
?DOC(" Decode a JSON number as Float, accepting both float and int values.\n").
-spec ws_number() -> gleam@dynamic@decode:decoder(float()).
ws_number() ->
gleam@dynamic@decode:one_of(
{decoder, fun gleam@dynamic@decode:decode_float/1},
[begin
_pipe = {decoder, fun gleam@dynamic@decode:decode_int/1},
gleam@dynamic@decode:map(_pipe, fun erlang:float/1)
end]
).
-file("src/glupbit/websocket/subscription.gleam", 245).
-spec ws_orderbook_unit_decoder() -> gleam@dynamic@decode:decoder(glupbit@quotation@orderbook:orderbook_unit()).
ws_orderbook_unit_decoder() ->
gleam@dynamic@decode:field(
<<"ask_price"/utf8>>,
ws_number(),
fun(Ask_price) ->
gleam@dynamic@decode:field(
<<"bid_price"/utf8>>,
ws_number(),
fun(Bid_price) ->
gleam@dynamic@decode:field(
<<"ask_size"/utf8>>,
ws_number(),
fun(Ask_size) ->
gleam@dynamic@decode:field(
<<"bid_size"/utf8>>,
ws_number(),
fun(Bid_size) ->
gleam@dynamic@decode:success(
{orderbook_unit,
Ask_price,
Bid_price,
Ask_size,
Bid_size}
)
end
)
end
)
end
)
end
).
-file("src/glupbit/websocket/subscription.gleam", 259).
?DOC(" Decoder for WebSocket orderbook data.\n").
-spec orderbook_data_decoder() -> gleam@dynamic@decode:decoder(orderbook_data()).
orderbook_data_decoder() ->
gleam@dynamic@decode:field(
<<"code"/utf8>>,
{decoder, fun gleam@dynamic@decode:decode_string/1},
fun(Code) ->
gleam@dynamic@decode:field(
<<"total_ask_size"/utf8>>,
ws_number(),
fun(Total_ask_size) ->
gleam@dynamic@decode:field(
<<"total_bid_size"/utf8>>,
ws_number(),
fun(Total_bid_size) ->
gleam@dynamic@decode:field(
<<"orderbook_units"/utf8>>,
gleam@dynamic@decode:list(
ws_orderbook_unit_decoder()
),
fun(Orderbook_units) ->
gleam@dynamic@decode:field(
<<"timestamp"/utf8>>,
{decoder,
fun gleam@dynamic@decode:decode_int/1},
fun(Timestamp) ->
gleam@dynamic@decode:success(
{orderbook_data,
Code,
Total_ask_size,
Total_bid_size,
Orderbook_units,
Timestamp}
)
end
)
end
)
end
)
end
)
end
).
-file("src/glupbit/websocket/subscription.gleam", 298).
?DOC(" Decoder for a single subscription info item.\n").
-spec subscription_info_decoder() -> gleam@dynamic@decode:decoder(subscription_info()).
subscription_info_decoder() ->
gleam@dynamic@decode:field(
<<"type"/utf8>>,
{decoder, fun gleam@dynamic@decode:decode_string/1},
fun(Type_name) ->
gleam@dynamic@decode:optional_field(
<<"codes"/utf8>>,
none,
gleam@dynamic@decode:optional(
gleam@dynamic@decode:list(
{decoder, fun gleam@dynamic@decode:decode_string/1}
)
),
fun(Codes) ->
gleam@dynamic@decode:optional_field(
<<"level"/utf8>>,
none,
gleam@dynamic@decode:optional(
{decoder, fun gleam@dynamic@decode:decode_float/1}
),
fun(Level) ->
gleam@dynamic@decode:success(
{subscription_info, Type_name, Codes, Level}
)
end
)
end
)
end
).
-file("src/glupbit/websocket/subscription.gleam", 314).
?DOC(" Decoder for the LIST_SUBSCRIPTIONS response message.\n").
-spec list_subscriptions_response_decoder() -> gleam@dynamic@decode:decoder(list_subscriptions_response()).
list_subscriptions_response_decoder() ->
gleam@dynamic@decode:field(
<<"method"/utf8>>,
{decoder, fun gleam@dynamic@decode:decode_string/1},
fun(Method) ->
gleam@dynamic@decode:field(
<<"result"/utf8>>,
gleam@dynamic@decode:list(subscription_info_decoder()),
fun(Result) ->
gleam@dynamic@decode:field(
<<"ticket"/utf8>>,
{decoder, fun gleam@dynamic@decode:decode_string/1},
fun(Ticket) ->
gleam@dynamic@decode:success(
{list_subscriptions_response,
Method,
Result,
Ticket}
)
end
)
end
)
end
).