Packages

Binding to Starling Bank's API

Current section

Files

Jump to
sturnidae src sturnidae.erl
Raw

src/sturnidae.erl

-module(sturnidae).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([direction_to_string/1, transaction_status_to_string/1, string_to_transaction_status/1, decode_feed_item/1, get_feed_items_response/1, get_feed_items_request/4]).
-export_type([starling_api_error/0, direction/0, currency_and_amount/0, transaction_status/0, feed_item/0]).
-type starling_api_error() :: {starling_client_error, integer(), list(binary())} |
{starling_server_error, integer(), binary()}.
-type direction() :: in | out.
-type currency_and_amount() :: {currency_and_amount, binary(), integer()}.
-type transaction_status() :: upcoming |
pending |
reversed |
settled |
declined |
refunded |
retrying |
account_check.
-type feed_item() :: {feed_item,
binary(),
binary(),
currency_and_amount(),
currency_and_amount(),
binary(),
direction(),
binary(),
binary(),
transaction_status(),
gleam@option:option(binary()),
gleam@option:option(binary()),
binary(),
gleam@option:option(integer()),
gleam@option:option(currency_and_amount()),
gleam@option:option(binary()),
binary(),
binary(),
gleam@option:option(binary())}.
-spec direction_to_string(direction()) -> binary().
direction_to_string(Direction) ->
case Direction of
in ->
<<"IN"/utf8>>;
out ->
<<"OUT"/utf8>>
end.
-spec transaction_status_to_string(transaction_status()) -> binary().
transaction_status_to_string(Status) ->
case Status of
upcoming ->
<<"UPCOMING"/utf8>>;
pending ->
<<"PENDING"/utf8>>;
reversed ->
<<"REVERSED"/utf8>>;
settled ->
<<"SETTLED"/utf8>>;
declined ->
<<"DECLINED"/utf8>>;
refunded ->
<<"REFUNDED"/utf8>>;
retrying ->
<<"RETRYING"/utf8>>;
account_check ->
<<"ACCOUNT_CHECK"/utf8>>
end.
-spec string_to_transaction_status(binary()) -> {ok, transaction_status()} |
{error, nil}.
string_to_transaction_status(Status) ->
case Status of
<<"UPCOMING"/utf8>> ->
{ok, upcoming};
<<"PENDING"/utf8>> ->
{ok, pending};
<<"REVERSED"/utf8>> ->
{ok, reversed};
<<"SETTLED"/utf8>> ->
{ok, settled};
<<"DECLINED"/utf8>> ->
{ok, declined};
<<"REFUNDED"/utf8>> ->
{ok, refunded};
<<"RETRYING"/utf8>> ->
{ok, retrying};
<<"ACCOUNT_CHECK"/utf8>> ->
{ok, account_check};
_ ->
{error, nil}
end.
-spec decode_currency_and_amount(gleam@dynamic:dynamic_()) -> {ok,
currency_and_amount()} |
{error, list(gleam@dynamic:decode_error())}.
decode_currency_and_amount(D) ->
gleam@result:'try'(
(gleam@dynamic:field(<<"currency"/utf8>>, fun gleam@dynamic:string/1))(
D
),
fun(Currency) ->
gleam@result:'try'(
(gleam@dynamic:field(
<<"minorUnits"/utf8>>,
fun gleam@dynamic:int/1
))(D),
fun(Minor_units) ->
{ok, {currency_and_amount, Currency, Minor_units}}
end
)
end
).
-spec decode_direction(gleam@dynamic:dynamic_()) -> {ok, direction()} |
{error, list(gleam@dynamic:decode_error())}.
decode_direction(D) ->
gleam@result:'try'(
gleam@dynamic:string(D),
fun(Direction) -> case Direction of
<<"IN"/utf8>> ->
{ok, in};
<<"OUT"/utf8>> ->
{ok, out};
_ ->
{error,
[{decode_error,
<<"Direction"/utf8>>,
<<"String"/utf8>>,
[]}]}
end end
).
-spec decode_transaction_status(gleam@dynamic:dynamic_()) -> {ok,
transaction_status()} |
{error, list(gleam@dynamic:decode_error())}.
decode_transaction_status(D) ->
gleam@result:'try'(gleam@dynamic:string(D), fun(Status) -> case Status of
<<"UPCOMING"/utf8>> ->
{ok, upcoming};
<<"PENDING"/utf8>> ->
{ok, pending};
<<"REVERSED"/utf8>> ->
{ok, reversed};
<<"SETTLED"/utf8>> ->
{ok, settled};
<<"DECLINED"/utf8>> ->
{ok, declined};
<<"REFUNDED"/utf8>> ->
{ok, refunded};
<<"RETRYING"/utf8>> ->
{ok, retrying};
<<"ACCOUNT_CHECK"/utf8>> ->
{ok, account_check};
_ ->
{error,
[{decode_error,
<<"TransactionStatus"/utf8>>,
<<"String"/utf8>>,
[]}]}
end end).
-spec decode_feed_item(gleam@dynamic:dynamic_()) -> {ok, feed_item()} |
{error, list(gleam@dynamic:decode_error())}.
decode_feed_item(D) ->
String_field = fun(Field) ->
(gleam@dynamic:field(Field, fun gleam@dynamic:string/1))(D)
end,
gleam@result:'try'(
String_field(<<"feedItemUid"/utf8>>),
fun(Feed_item_uid) ->
gleam@result:'try'(
String_field(<<"categoryUid"/utf8>>),
fun(Category_uid) ->
gleam@result:'try'(
(gleam@dynamic:field(
<<"amount"/utf8>>,
fun decode_currency_and_amount/1
))(D),
fun(Amount) ->
gleam@result:'try'(
(gleam@dynamic:field(
<<"sourceAmount"/utf8>>,
fun decode_currency_and_amount/1
))(D),
fun(Source_amount) ->
gleam@result:'try'(
String_field(<<"updatedAt"/utf8>>),
fun(Updated_at) ->
gleam@result:'try'(
(gleam@dynamic:field(
<<"direction"/utf8>>,
fun decode_direction/1
))(D),
fun(Direction) ->
gleam@result:'try'(
String_field(
<<"transactionTime"/utf8>>
),
fun(Transaction_time) ->
gleam@result:'try'(
String_field(
<<"source"/utf8>>
),
fun(Source) ->
gleam@result:'try'(
(gleam@dynamic:field(
<<"status"/utf8>>,
fun decode_transaction_status/1
))(D),
fun(
Status
) ->
gleam@result:'try'(
(gleam@dynamic:optional_field(
<<"counterPartyType"/utf8>>,
fun gleam@dynamic:string/1
))(
D
),
fun(
Counter_party_type
) ->
gleam@result:'try'(
(gleam@dynamic:optional_field(
<<"counterPartyUid"/utf8>>,
fun gleam@dynamic:string/1
))(
D
),
fun(
Counter_party_uid
) ->
gleam@result:'try'(
String_field(
<<"counterPartyName"/utf8>>
),
fun(
Counter_party_name
) ->
gleam@result:'try'(
(gleam@dynamic:optional_field(
<<"totalFees"/utf8>>,
fun gleam@dynamic:int/1
))(
D
),
fun(
Total_fees
) ->
gleam@result:'try'(
(gleam@dynamic:optional_field(
<<"totalFeeAmount"/utf8>>,
fun decode_currency_and_amount/1
))(
D
),
fun(
Total_fee_amount
) ->
gleam@result:'try'(
(gleam@dynamic:optional_field(
<<"reference"/utf8>>,
fun gleam@dynamic:string/1
))(
D
),
fun(
Reference
) ->
gleam@result:'try'(
String_field(
<<"country"/utf8>>
),
fun(
Country
) ->
gleam@result:'try'(
String_field(
<<"spendingCategory"/utf8>>
),
fun(
Spending_category
) ->
gleam@result:'try'(
(gleam@dynamic:optional_field(
<<"userNote"/utf8>>,
fun gleam@dynamic:string/1
))(
D
),
fun(
User_note
) ->
{ok,
{feed_item,
Feed_item_uid,
Category_uid,
Amount,
Source_amount,
Updated_at,
Direction,
Transaction_time,
Source,
Status,
Counter_party_type,
Counter_party_uid,
Counter_party_name,
Total_fees,
Total_fee_amount,
Reference,
Country,
Spending_category,
User_note}}
end
)
end
)
end
)
end
)
end
)
end
)
end
)
end
)
end
)
end
)
end
)
end
)
end
)
end
)
end
)
end
)
end
)
end
).
-spec check_status(gleam@http@response:response(binary())) -> {ok, nil} |
{error, starling_api_error()}.
check_status(Response) ->
Status = erlang:element(2, Response),
case nil of
_ when (Status >= 200) andalso (Status < 300) ->
{ok, nil};
_ when (Status >= 400) andalso (Status < 500) ->
Messages = [],
{error, {starling_client_error, Status, Messages}};
_ ->
{error,
{starling_server_error, Status, erlang:element(4, Response)}}
end.
-spec decode_json_body(
gleam@http@response:response(binary()),
fun((gleam@dynamic:dynamic_()) -> {ok, GUJ} |
{error, list(gleam@dynamic:decode_error())})
) -> {ok, GUJ} | {error, starling_api_error()}.
decode_json_body(Response, Decoder) ->
case gleam@json:decode(erlang:element(4, Response), Decoder) of
{ok, Json} ->
{ok, Json};
{error, _} ->
{error,
{starling_server_error,
erlang:element(2, Response),
<<"Invalid JSON returned by server"/utf8>>}}
end.
-spec get_feed_items_response(gleam@http@response:response(binary())) -> {ok,
list(feed_item())} |
{error, starling_api_error()}.
get_feed_items_response(Response) ->
gleam@result:'try'(
check_status(Response),
fun(_) ->
Decoder = gleam@dynamic:field(
<<"feedItems"/utf8>>,
gleam@dynamic:list(fun decode_feed_item/1)
),
decode_json_body(Response, Decoder)
end
).
-spec get_feed_items_request(binary(), binary(), binary(), binary()) -> gleam@http@request:request(binary()).
get_feed_items_request(Pat, Account, Category, Limit) ->
Url = <<<<<<<<"https://api.starlingbank.com/api/v2"/utf8,
"/feed/account/"/utf8>>/binary,
Account/binary>>/binary,
"/category/"/utf8>>/binary,
Category/binary>>,
Url@1 = <<<<Url/binary, "?changesSince="/utf8>>/binary, Limit/binary>>,
_assert_subject = gleam@http@request:to(Url@1),
{ok, Request} = case _assert_subject of
{ok, _} -> _assert_subject;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail,
module => <<"sturnidae"/utf8>>,
function => <<"get_feed_items_request"/utf8>>,
line => 233})
end,
_pipe = Request,
_pipe@1 = gleam@http@request:set_header(
_pipe,
<<"accept"/utf8>>,
<<"application/json"/utf8>>
),
gleam@http@request:set_header(
_pipe@1,
<<"authorization"/utf8>>,
<<"Bearer "/utf8, Pat/binary>>
).