TD-330: Limiter (#35)

* bumped deps

* added rebar plugin

* added limiter support

* bumped to
valitydev/binbase-proto@6841072
valitydev/fistful-proto@a3e89bc
valitydev/machinegun-proto@a411c7d

* refactored withdrawal routing, fixed dialyzer, fixed fmt and lint

* added limiter to compose, added limiter suite wip

* finished tests

* fixed dialyzer

* fixed eunit

* fixed tests

* fixed services

* added part of fixes

* added new test case and some refactor

* closed to finish

* added rejected logging

* added requested changes

* fixed
This commit is contained in:
Артем 2022-08-04 12:18:02 +03:00 committed by GitHub
parent e9e05cee92
commit 6ba2c49bbd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
108 changed files with 1988 additions and 791 deletions

2
.env
View File

@ -4,4 +4,4 @@
SERVICE_NAME=fistful-server
OTP_VERSION=24.2.0
REBAR_VERSION=3.18
THRIFT_VERSION=0.14.2.2
THRIFT_VERSION=0.14.2.3

View File

@ -29,10 +29,11 @@ jobs:
run:
name: Run checks
needs: setup
uses: valitydev/erlang-workflows/.github/workflows/erlang-parallel-build.yml@v1.0.2
uses: valitydev/erlang-workflows/.github/workflows/erlang-parallel-build.yml@v1.0.3
with:
otp-version: ${{ needs.setup.outputs.otp-version }}
rebar-version: ${{ needs.setup.outputs.rebar-version }}
use-thrift: true
thrift-version: ${{ needs.setup.outputs.thrift-version }}
run-ct-with-compose: true
cache-version: v2

View File

@ -1,10 +1,17 @@
-ifndef(__ct_domain_hrl__).
-define(__ct_domain_hrl__, 42).
-include_lib("damsel/include/dmsl_domain_config_thrift.hrl").
-include_lib("damsel/include/dmsl_domain_conf_thrift.hrl").
-include_lib("damsel/include/dmsl_domain_thrift.hrl").
-include_lib("damsel/include/dmsl_base_thrift.hrl").
-define(ordset(Es), ordsets:from_list(Es)).
-define(LIMIT_TURNOVER_NUM_PAYTOOL_ID1, <<"ID1">>).
-define(LIMIT_TURNOVER_NUM_PAYTOOL_ID2, <<"ID2">>).
-define(LIMIT_TURNOVER_AMOUNT_PAYTOOL_ID1, <<"ID3">>).
-define(LIMIT_TURNOVER_AMOUNT_PAYTOOL_ID2, <<"ID4">>).
-define(glob(), #domain_GlobalsRef{}).
-define(cur(ID), #domain_CurrencyRef{symbolic_code = ID}).
-define(pmt(C, T), #domain_PaymentMethodRef{id = {C, T}}).
@ -23,6 +30,7 @@
-define(insp(ID), #domain_InspectorRef{id = ID}).
-define(payinst(ID), #domain_PaymentInstitutionRef{id = ID}).
-define(ruleset(ID), #domain_RoutingRulesetRef{id = ID}).
-define(trnvrlimit(ID, UpperBoundary), #domain_TurnoverLimit{id = ID, upper_boundary = UpperBoundary}).
-define(cash(Amount, SymCode), #domain_Cash{amount = Amount, currency = ?cur(SymCode)}).
@ -39,14 +47,14 @@
-define(share(P, Q, C),
{share, #domain_CashVolumeShare{
parts = #'Rational'{p = P, q = Q},
parts = #'base_Rational'{p = P, q = Q},
'of' = C
}}
).
-define(share(P, Q, C, RM),
{share, #domain_CashVolumeShare{
parts = #'Rational'{p = P, q = Q},
parts = #'base_Rational'{p = P, q = Q},
'of' = C,
'rounding_method' = RM
}}

View File

@ -30,6 +30,7 @@
%%
-include_lib("ff_cth/include/ct_domain.hrl").
-include_lib("damsel/include/dmsl_base_thrift.hrl").
-include_lib("damsel/include/dmsl_accounter_thrift.hrl").
-define(DTP(Type), dmsl_domain_thrift:Type()).
@ -133,8 +134,7 @@ category(Ref, Name, Type) ->
}}.
-spec payment_method(?DTP('PaymentMethodRef')) -> object().
payment_method(?pmt(_Type, Name) = Ref) when is_atom(Name) ->
payment_method(erlang:atom_to_binary(Name, unicode), Ref);
payment_method(?pmt(?PAYMENT_METHOD_BANK_CARD(ID)) = Ref) when is_binary(ID) ->
payment_method(ID, Ref);
payment_method(?pmt(?PAYMENT_METHOD_DIGITAL_WALLET(ID)) = Ref) when is_binary(ID) ->
@ -291,7 +291,7 @@ term_set_hierarchy(Ref, ParentRef, TermSets) ->
-spec timed_term_set(?DTP('TermSet')) -> ?DTP('TimedTermSet').
timed_term_set(TermSet) ->
#domain_TimedTermSet{
action_time = #'TimestampInterval'{},
action_time = #'base_TimestampInterval'{},
terms = TermSet
}.

View File

@ -17,7 +17,7 @@
%%
-include_lib("damsel/include/dmsl_domain_config_thrift.hrl").
-include_lib("damsel/include/dmsl_domain_conf_thrift.hrl").
-type revision() :: dmt_client:version().
-type object() :: dmsl_domain_thrift:'DomainObject'().
@ -28,7 +28,7 @@ head() ->
-spec all(revision()) -> dmsl_domain_thrift:'Domain'().
all(Revision) ->
#'Snapshot'{domain = Domain} = dmt_client:checkout(Revision),
#'domain_conf_Snapshot'{domain = Domain} = dmt_client:checkout(Revision),
Domain.
-spec commit(revision(), dmt_client:commit()) -> revision() | no_return().
@ -61,9 +61,9 @@ reset(Revision) ->
-spec cleanup() -> revision() | no_return().
cleanup() ->
#'Snapshot'{domain = Domain} = dmt_client:checkout(latest),
#'domain_conf_Snapshot'{domain = Domain} = dmt_client:checkout(latest),
remove(maps:values(Domain)).
-spec bump_revision() -> revision() | no_return().
bump_revision() ->
dmt_client:commit(#'Commit'{ops = []}).
dmt_client:commit(#'domain_conf_Commit'{ops = []}).

View File

@ -1,28 +1,29 @@
-module(ct_eventsink).
-include_lib("fistful_proto/include/ff_proto_identity_thrift.hrl").
-include_lib("fistful_proto/include/ff_proto_wallet_thrift.hrl").
-include_lib("fistful_proto/include/ff_proto_withdrawal_thrift.hrl").
-include_lib("fistful_proto/include/ff_proto_withdrawal_session_thrift.hrl").
-include_lib("fistful_proto/include/ff_proto_destination_thrift.hrl").
-include_lib("fistful_proto/include/ff_proto_source_thrift.hrl").
-include_lib("fistful_proto/include/ff_proto_deposit_thrift.hrl").
-include_lib("fistful_proto/include/ff_proto_w2w_transfer_thrift.hrl").
-include_lib("fistful_proto/include/fistful_identity_thrift.hrl").
-include_lib("fistful_proto/include/fistful_wallet_thrift.hrl").
-include_lib("fistful_proto/include/fistful_wthd_thrift.hrl").
-include_lib("fistful_proto/include/fistful_wthd_session_thrift.hrl").
-include_lib("fistful_proto/include/fistful_destination_thrift.hrl").
-include_lib("fistful_proto/include/fistful_source_thrift.hrl").
-include_lib("fistful_proto/include/fistful_deposit_thrift.hrl").
-include_lib("fistful_proto/include/fistful_w2w_transfer_thrift.hrl").
-include_lib("fistful_proto/include/fistful_evsink_thrift.hrl").
-type sink() ::
ff_services:service_name().
-type event() ::
ff_proto_wallet_thrift:'SinkEvent'()
| ff_proto_withdrawal_thrift:'SinkEvent'()
| ff_proto_identity_thrift:'SinkEvent'()
| ff_proto_destination_thrift:'SinkEvent'()
| ff_proto_source_thrift:'SinkEvent'()
| ff_proto_deposit_thrift:'SinkEvent'()
| ff_proto_withdrawal_thrift:'SinkEvent'()
| ff_proto_w2w_transfer_thrift:'SinkEvent'().
fistful_wallet_thrift:'SinkEvent'()
| fistful_wthd_thrift:'SinkEvent'()
| fistful_identity_thrift:'SinkEvent'()
| fistful_destination_thrift:'SinkEvent'()
| fistful_source_thrift:'SinkEvent'()
| fistful_deposit_thrift:'SinkEvent'()
| fistful_wthd_thrift:'SinkEvent'()
| fistful_w2w_transfer_thrift:'SinkEvent'().
-type event_id() :: ff_proto_eventsink_thrift:'EventID'().
-type event_id() :: fistful_evsink_thrift:'EventID'().
-type limit() :: non_neg_integer().
-export([last_id/1]).
@ -73,11 +74,11 @@ get_max_event_id(Events) when is_list(Events) ->
lists:foldl(fun(Ev, Max) -> erlang:max(get_event_id(Ev), Max) end, 0, Events).
-spec get_event_id(event()) -> event_id().
get_event_id(#'wlt_SinkEvent'{id = ID}) -> ID;
get_event_id(#'wallet_SinkEvent'{id = ID}) -> ID;
get_event_id(#'wthd_SinkEvent'{id = ID}) -> ID;
get_event_id(#'idnt_SinkEvent'{id = ID}) -> ID;
get_event_id(#'dst_SinkEvent'{id = ID}) -> ID;
get_event_id(#'src_SinkEvent'{id = ID}) -> ID;
get_event_id(#'identity_SinkEvent'{id = ID}) -> ID;
get_event_id(#'destination_SinkEvent'{id = ID}) -> ID;
get_event_id(#'source_SinkEvent'{id = ID}) -> ID;
get_event_id(#'deposit_SinkEvent'{id = ID}) -> ID;
get_event_id(#'wthd_session_SinkEvent'{id = ID}) -> ID;
get_event_id(#'w2w_transfer_SinkEvent'{id = ID}) -> ID.

View File

@ -89,30 +89,30 @@ start_processing_apps(Options) ->
handlers => [
{
<<"/bank">>,
{{dmsl_withdrawals_provider_adapter_thrift, 'Adapter'}, {ff_ct_provider_handler, []}}
{{dmsl_wthd_provider_thrift, 'Adapter'}, {ff_ct_provider_handler, []}}
},
{
<<"/quotebank">>,
{{dmsl_withdrawals_provider_adapter_thrift, 'Adapter'}, {ff_ct_provider_handler, []}}
{{dmsl_wthd_provider_thrift, 'Adapter'}, {ff_ct_provider_handler, []}}
},
{
<<"/downbank">>,
{
{dmsl_withdrawals_provider_adapter_thrift, 'Adapter'},
{dmsl_wthd_provider_thrift, 'Adapter'},
{ff_ct_provider_handler, [{handler, ff_ct_fail_provider}]}
}
},
{
<<"/downbank2">>,
{
{dmsl_withdrawals_provider_adapter_thrift, 'Adapter'},
{dmsl_wthd_provider_thrift, 'Adapter'},
{ff_ct_provider_handler, [{handler, ff_ct_unknown_failure_provider}]}
}
},
{
<<"/sleepybank">>,
{
{dmsl_withdrawals_provider_adapter_thrift, 'Adapter'},
{dmsl_wthd_provider_thrift, 'Adapter'},
{ff_ct_provider_handler, [{handler, ff_ct_sleepy_provider}]}
}
},
@ -232,7 +232,8 @@ services(Options) ->
automaton => "http://machinegun:8022/v1/automaton",
accounter => "http://shumway:8022/accounter",
partymgmt => "http://party-management:8022/v1/processing/partymgmt",
binbase => "http://localhost:8222/binbase"
binbase => "http://localhost:8222/binbase",
limiter => "http://limiter:8022/v1/limiter"
},
maps:get(services, Options, Default).
@ -365,6 +366,26 @@ domain_config(Options) ->
condition(cost_in, {700700, <<"RUB">>}),
?ruleset(?PAYINST1_ROUTING_POLICIES + 13)
),
delegate(
condition(cost_in, {800800, <<"RUB">>}),
?ruleset(?PAYINST1_ROUTING_POLICIES + 16)
),
delegate(
condition(cost_in, {900900, <<"RUB">>}),
?ruleset(?PAYINST1_ROUTING_POLICIES + 17)
),
delegate(
condition(cost_in, {901000, <<"RUB">>}),
?ruleset(?PAYINST1_ROUTING_POLICIES + 18)
),
delegate(
condition(cost_in, {902000, <<"RUB">>}),
?ruleset(?PAYINST1_ROUTING_POLICIES + 19)
),
delegate(
condition(cost_in, {903000, <<"RUB">>}),
?ruleset(?PAYINST1_ROUTING_POLICIES + 19)
),
delegate(
{condition,
{payment_tool,
@ -466,6 +487,36 @@ domain_config(Options) ->
]}
),
routing_ruleset(
?ruleset(?PAYINST1_ROUTING_POLICIES + 16),
{candidates, [
candidate({constant, true}, ?trm(1800))
]}
),
routing_ruleset(
?ruleset(?PAYINST1_ROUTING_POLICIES + 17),
{candidates, [
candidate({constant, true}, ?trm(1900))
]}
),
routing_ruleset(
?ruleset(?PAYINST1_ROUTING_POLICIES + 18),
{candidates, [
candidate({constant, true}, ?trm(2000), 1000),
candidate({constant, true}, ?trm(1900), 4000)
]}
),
routing_ruleset(
?ruleset(?PAYINST1_ROUTING_POLICIES + 19),
{candidates, [
candidate({constant, true}, ?trm(2200), 1000),
candidate({constant, true}, ?trm(2100), 4000)
]}
),
routing_ruleset(
?ruleset(?PAYINST1_ROUTING_PROHIBITIONS),
<<"PayInst1 Withdrawal Prohibitions">>,
@ -721,6 +772,82 @@ domain_config(Options) ->
}
),
ct_domain:withdrawal_terminal(
?trm(1800),
?prv(1),
#domain_ProvisionTermSet{
wallet = #domain_WalletProvisionTerms{
withdrawals = #domain_WithdrawalProvisionTerms{
currencies = {value, ?ordset([?cur(<<"RUB">>), ?cur(<<"BTC">>)])},
turnover_limit =
{value, [
?trnvrlimit(?LIMIT_TURNOVER_NUM_PAYTOOL_ID1, 1000)
]}
}
}
}
),
ct_domain:withdrawal_terminal(
?trm(1900),
?prv(1),
#domain_ProvisionTermSet{
wallet = #domain_WalletProvisionTerms{
withdrawals = #domain_WithdrawalProvisionTerms{
turnover_limit =
{value, [
?trnvrlimit(?LIMIT_TURNOVER_NUM_PAYTOOL_ID2, 0)
]}
}
}
}
),
ct_domain:withdrawal_terminal(
?trm(2000),
?prv(1),
#domain_ProvisionTermSet{
wallet = #domain_WalletProvisionTerms{
withdrawals = #domain_WithdrawalProvisionTerms{
turnover_limit =
{value, [
?trnvrlimit(?LIMIT_TURNOVER_NUM_PAYTOOL_ID2, 1000)
]}
}
}
}
),
ct_domain:withdrawal_terminal(
?trm(2100),
?prv(1),
#domain_ProvisionTermSet{
wallet = #domain_WalletProvisionTerms{
withdrawals = #domain_WithdrawalProvisionTerms{
turnover_limit =
{value, [
?trnvrlimit(?LIMIT_TURNOVER_AMOUNT_PAYTOOL_ID1, 1804000)
]}
}
}
}
),
ct_domain:withdrawal_terminal(
?trm(2200),
?prv(1),
#domain_ProvisionTermSet{
wallet = #domain_WalletProvisionTerms{
withdrawals = #domain_WithdrawalProvisionTerms{
turnover_limit =
{value, [
?trnvrlimit(?LIMIT_TURNOVER_AMOUNT_PAYTOOL_ID2, 903000)
]}
}
}
}
),
ct_domain:currency(?cur(<<"RUB">>)),
ct_domain:currency(?cur(<<"USD">>)),
ct_domain:currency(?cur(<<"EUR">>)),

View File

@ -2,7 +2,7 @@
-behaviour(ff_codec).
-include_lib("fistful_proto/include/ff_proto_cashflow_thrift.hrl").
-include_lib("fistful_proto/include/fistful_cashflow_thrift.hrl").
-export([marshal/2]).
-export([unmarshal/2]).

View File

@ -1,9 +1,11 @@
-module(ff_codec).
-include_lib("fistful_proto/include/ff_proto_base_thrift.hrl").
-include_lib("fistful_proto/include/ff_proto_repairer_thrift.hrl").
-include_lib("fistful_proto/include/ff_proto_account_thrift.hrl").
-include_lib("fistful_proto/include/ff_proto_msgpack_thrift.hrl").
-include_lib("fistful_proto/include/fistful_fistful_base_thrift.hrl").
-include_lib("fistful_proto/include/fistful_repairer_thrift.hrl").
-include_lib("fistful_proto/include/fistful_account_thrift.hrl").
-include_lib("fistful_proto/include/fistful_msgp_thrift.hrl").
-include_lib("fistful_proto/include/fistful_fistful_thrift.hrl").
-include_lib("fistful_proto/include/fistful_evsink_thrift.hrl").
-export([unmarshal/2]).
-export([unmarshal/3]).
@ -354,7 +356,7 @@ unmarshal(three_ds_verification, Value) when
Value =:= authentication_could_not_be_performed
->
Value;
unmarshal(complex_action, #ff_repairer_ComplexAction{
unmarshal(complex_action, #repairer_ComplexAction{
timer = TimerAction,
remove = RemoveAction
}) ->
@ -363,13 +365,13 @@ unmarshal(timer_action, undefined) ->
[];
unmarshal(timer_action, {set_timer, SetTimerAction}) ->
[{set_timer, unmarshal(set_timer_action, SetTimerAction)}];
unmarshal(timer_action, {unset_timer, #ff_repairer_UnsetTimerAction{}}) ->
unmarshal(timer_action, {unset_timer, #repairer_UnsetTimerAction{}}) ->
[unset_timer];
unmarshal(remove_action, undefined) ->
[];
unmarshal(remove_action, #ff_repairer_RemoveAction{}) ->
unmarshal(remove_action, #repairer_RemoveAction{}) ->
[remove];
unmarshal(set_timer_action, #ff_repairer_SetTimerAction{
unmarshal(set_timer_action, #repairer_SetTimerAction{
timer = Timer
}) ->
unmarshal(timer, Timer);
@ -614,7 +616,7 @@ bank_card_codec_test() ->
auth_data => {session, #{session_id => <<"session_id">>}}
}},
{bank_card, MarshalledResourceBankCard} = marshal(resource, ResourceBankCard),
Type = {struct, struct, {ff_proto_base_thrift, 'ResourceBankCard'}},
Type = {struct, struct, {fistful_fistful_base_thrift, 'ResourceBankCard'}},
Binary = ff_proto_utils:serialize(Type, MarshalledResourceBankCard),
Decoded = ff_proto_utils:deserialize(Type, Binary),
?assertEqual(
@ -646,7 +648,7 @@ generic_resource_codec_test() ->
provider => #{id => <<"foo">>},
data => #{type => <<"type">>, data => <<"data">>}
},
Type = {struct, struct, {ff_proto_base_thrift, 'ResourceGenericData'}},
Type = {struct, struct, {fistful_fistful_base_thrift, 'ResourceGenericData'}},
Binary = ff_proto_utils:serialize(Type, marshal(generic_resource, GenericResource)),
Decoded = ff_proto_utils:deserialize(Type, Binary),
?assertEqual(
@ -666,7 +668,7 @@ fees_codec_test() ->
surplus => {200, <<"RUB">>}
}
},
Type = {struct, struct, {ff_proto_base_thrift, 'Fees'}},
Type = {struct, struct, {fistful_fistful_base_thrift, 'Fees'}},
Binary = ff_proto_utils:serialize(Type, marshal(fees, Expected)),
Decoded = ff_proto_utils:deserialize(Type, Binary),
?assertEqual(Expected, unmarshal(fees, Decoded)).

View File

@ -2,7 +2,7 @@
-behaviour(ff_codec).
-include_lib("fistful_proto/include/ff_proto_deposit_adjustment_thrift.hrl").
-include_lib("fistful_proto/include/fistful_deposit_adj_thrift.hrl").
-export([marshal/2]).
-export([unmarshal/2]).
@ -11,13 +11,13 @@
-spec marshal(ff_codec:type_name(), ff_codec:decoded_value()) -> ff_codec:encoded_value().
marshal(change, {created, Adjustment}) ->
{created, #dep_adj_CreatedChange{adjustment = marshal(adjustment, Adjustment)}};
{created, #deposit_adj_CreatedChange{adjustment = marshal(adjustment, Adjustment)}};
marshal(change, {status_changed, Status}) ->
{status_changed, #dep_adj_StatusChange{status = marshal(status, Status)}};
{status_changed, #deposit_adj_StatusChange{status = marshal(status, Status)}};
marshal(change, {p_transfer, TransferChange}) ->
{transfer, #dep_adj_TransferChange{payload = ff_p_transfer_codec:marshal(change, TransferChange)}};
{transfer, #deposit_adj_TransferChange{payload = ff_p_transfer_codec:marshal(change, TransferChange)}};
marshal(adjustment, Adjustment) ->
#dep_adj_Adjustment{
#deposit_adj_Adjustment{
id = marshal(id, ff_adjustment:id(Adjustment)),
status = maybe_marshal(status, ff_adjustment:status(Adjustment)),
changes_plan = marshal(changes_plan, ff_adjustment:changes_plan(Adjustment)),
@ -28,13 +28,13 @@ marshal(adjustment, Adjustment) ->
external_id = maybe_marshal(id, ff_adjustment:external_id(Adjustment))
};
marshal(adjustment_params, Params) ->
#dep_adj_AdjustmentParams{
#deposit_adj_AdjustmentParams{
id = marshal(id, maps:get(id, Params)),
change = marshal(change_request, maps:get(change, Params)),
external_id = maybe_marshal(id, maps:get(external_id, Params, undefined))
};
marshal(adjustment_state, Adjustment) ->
#dep_adj_AdjustmentState{
#deposit_adj_AdjustmentState{
id = marshal(id, ff_adjustment:id(Adjustment)),
status = maybe_marshal(status, ff_adjustment:status(Adjustment)),
changes_plan = marshal(changes_plan, ff_adjustment:changes_plan(Adjustment)),
@ -45,79 +45,79 @@ marshal(adjustment_state, Adjustment) ->
external_id = maybe_marshal(id, ff_adjustment:external_id(Adjustment))
};
marshal(status, pending) ->
{pending, #dep_adj_Pending{}};
{pending, #deposit_adj_Pending{}};
marshal(status, succeeded) ->
{succeeded, #dep_adj_Succeeded{}};
{succeeded, #deposit_adj_Succeeded{}};
marshal(changes_plan, Plan) ->
#dep_adj_ChangesPlan{
#deposit_adj_ChangesPlan{
new_cash_flow = maybe_marshal(cash_flow_change_plan, maps:get(new_cash_flow, Plan, undefined)),
new_status = maybe_marshal(status_change_plan, maps:get(new_status, Plan, undefined))
};
marshal(cash_flow_change_plan, Plan) ->
OldCashFLow = ff_cash_flow_codec:marshal(final_cash_flow, maps:get(old_cash_flow_inverted, Plan)),
NewCashFlow = ff_cash_flow_codec:marshal(final_cash_flow, maps:get(new_cash_flow, Plan)),
#dep_adj_CashFlowChangePlan{
#deposit_adj_CashFlowChangePlan{
old_cash_flow_inverted = OldCashFLow,
new_cash_flow = NewCashFlow
};
marshal(status_change_plan, Plan) ->
#dep_adj_StatusChangePlan{
#deposit_adj_StatusChangePlan{
new_status = ff_deposit_status_codec:marshal(status, maps:get(new_status, Plan))
};
marshal(change_request, {change_status, Status}) ->
{change_status, #dep_adj_ChangeStatusRequest{
{change_status, #deposit_adj_ChangeStatusRequest{
new_status = ff_deposit_status_codec:marshal(status, Status)
}};
marshal(T, V) ->
ff_codec:marshal(T, V).
-spec unmarshal(ff_codec:type_name(), ff_codec:encoded_value()) -> ff_codec:decoded_value().
unmarshal(change, {created, #dep_adj_CreatedChange{adjustment = Adjustment}}) ->
unmarshal(change, {created, #deposit_adj_CreatedChange{adjustment = Adjustment}}) ->
{created, unmarshal(adjustment, Adjustment)};
unmarshal(change, {status_changed, #dep_adj_StatusChange{status = Status}}) ->
unmarshal(change, {status_changed, #deposit_adj_StatusChange{status = Status}}) ->
{status_changed, unmarshal(status, Status)};
unmarshal(change, {transfer, #dep_adj_TransferChange{payload = TransferChange}}) ->
unmarshal(change, {transfer, #deposit_adj_TransferChange{payload = TransferChange}}) ->
{p_transfer, ff_p_transfer_codec:unmarshal(change, TransferChange)};
unmarshal(adjustment, Adjustment) ->
#{
id => unmarshal(id, Adjustment#dep_adj_Adjustment.id),
status => unmarshal(status, Adjustment#dep_adj_Adjustment.status),
changes_plan => unmarshal(changes_plan, Adjustment#dep_adj_Adjustment.changes_plan),
created_at => unmarshal(timestamp_ms, Adjustment#dep_adj_Adjustment.created_at),
domain_revision => unmarshal(domain_revision, Adjustment#dep_adj_Adjustment.domain_revision),
party_revision => unmarshal(party_revision, Adjustment#dep_adj_Adjustment.party_revision),
operation_timestamp => unmarshal(timestamp_ms, Adjustment#dep_adj_Adjustment.operation_timestamp),
external_id => maybe_unmarshal(id, Adjustment#dep_adj_Adjustment.external_id)
id => unmarshal(id, Adjustment#deposit_adj_Adjustment.id),
status => unmarshal(status, Adjustment#deposit_adj_Adjustment.status),
changes_plan => unmarshal(changes_plan, Adjustment#deposit_adj_Adjustment.changes_plan),
created_at => unmarshal(timestamp_ms, Adjustment#deposit_adj_Adjustment.created_at),
domain_revision => unmarshal(domain_revision, Adjustment#deposit_adj_Adjustment.domain_revision),
party_revision => unmarshal(party_revision, Adjustment#deposit_adj_Adjustment.party_revision),
operation_timestamp => unmarshal(timestamp_ms, Adjustment#deposit_adj_Adjustment.operation_timestamp),
external_id => maybe_unmarshal(id, Adjustment#deposit_adj_Adjustment.external_id)
};
unmarshal(adjustment_params, Params) ->
genlib_map:compact(#{
id => unmarshal(id, Params#dep_adj_AdjustmentParams.id),
change => unmarshal(change_request, Params#dep_adj_AdjustmentParams.change),
external_id => maybe_unmarshal(id, Params#dep_adj_AdjustmentParams.external_id)
id => unmarshal(id, Params#deposit_adj_AdjustmentParams.id),
change => unmarshal(change_request, Params#deposit_adj_AdjustmentParams.change),
external_id => maybe_unmarshal(id, Params#deposit_adj_AdjustmentParams.external_id)
});
unmarshal(status, {pending, #dep_adj_Pending{}}) ->
unmarshal(status, {pending, #deposit_adj_Pending{}}) ->
pending;
unmarshal(status, {succeeded, #dep_adj_Succeeded{}}) ->
unmarshal(status, {succeeded, #deposit_adj_Succeeded{}}) ->
succeeded;
unmarshal(changes_plan, Plan) ->
genlib_map:compact(#{
new_cash_flow => maybe_unmarshal(cash_flow_change_plan, Plan#dep_adj_ChangesPlan.new_cash_flow),
new_status => maybe_unmarshal(status_change_plan, Plan#dep_adj_ChangesPlan.new_status)
new_cash_flow => maybe_unmarshal(cash_flow_change_plan, Plan#deposit_adj_ChangesPlan.new_cash_flow),
new_status => maybe_unmarshal(status_change_plan, Plan#deposit_adj_ChangesPlan.new_status)
});
unmarshal(cash_flow_change_plan, Plan) ->
OldCashFlow = Plan#dep_adj_CashFlowChangePlan.old_cash_flow_inverted,
NewCashFlow = Plan#dep_adj_CashFlowChangePlan.new_cash_flow,
OldCashFlow = Plan#deposit_adj_CashFlowChangePlan.old_cash_flow_inverted,
NewCashFlow = Plan#deposit_adj_CashFlowChangePlan.new_cash_flow,
#{
old_cash_flow_inverted => ff_cash_flow_codec:unmarshal(final_cash_flow, OldCashFlow),
new_cash_flow => ff_cash_flow_codec:unmarshal(final_cash_flow, NewCashFlow)
};
unmarshal(status_change_plan, Plan) ->
Status = Plan#dep_adj_StatusChangePlan.new_status,
Status = Plan#deposit_adj_StatusChangePlan.new_status,
#{
new_status => ff_deposit_status_codec:unmarshal(status, Status)
};
unmarshal(change_request, {change_status, Request}) ->
Status = Request#dep_adj_ChangeStatusRequest.new_status,
Status = Request#deposit_adj_ChangeStatusRequest.new_status,
{change_status, ff_deposit_status_codec:unmarshal(status, Status)};
unmarshal(T, V) ->
ff_codec:unmarshal(T, V).

View File

@ -2,14 +2,16 @@
-behaviour(ff_codec).
-include_lib("fistful_proto/include/ff_proto_deposit_thrift.hrl").
-include_lib("fistful_proto/include/fistful_deposit_thrift.hrl").
-include_lib("fistful_proto/include/fistful_deposit_status_thrift.hrl").
-include_lib("fistful_proto/include/fistful_fistful_base_thrift.hrl").
-export([marshal_deposit_state/2]).
-export([marshal/2]).
-export([unmarshal/2]).
-spec marshal_deposit_state(ff_deposit:deposit_state(), ff_entity_context:context()) ->
ff_proto_deposit_thrift:'DepositState'().
fistful_deposit_thrift:'DepositState'().
marshal_deposit_state(DepositState, Context) ->
CashFlow = ff_deposit:effective_final_cash_flow(DepositState),
Reverts = ff_deposit:reverts(DepositState),
@ -188,7 +190,7 @@ deposit_symmetry_test() ->
source_id = genlib:unique(),
wallet_id = genlib:unique(),
external_id = undefined,
status = {pending, #dep_status_Pending{}},
status = {pending, #deposit_status_Pending{}},
id = genlib:unique(),
domain_revision = 24500062,
party_revision = 140028,
@ -231,7 +233,7 @@ deposit_timestamped_change_codec_test() ->
},
Change = {created, Deposit},
TimestampedChange = {ev, machinery_time:now(), Change},
Type = {struct, struct, {ff_proto_deposit_thrift, 'TimestampedChange'}},
Type = {struct, struct, {fistful_deposit_thrift, 'TimestampedChange'}},
Binary = ff_proto_utils:serialize(Type, marshal(timestamped_change, TimestampedChange)),
Decoded = ff_proto_utils:deserialize(Type, Binary),
?assertEqual(TimestampedChange, unmarshal(timestamped_change, Decoded)).
@ -255,7 +257,7 @@ deposit_change_revert_codec_test() ->
},
Change = {revert, Revert},
TimestampedChange = {ev, machinery_time:now(), Change},
Type = {struct, struct, {ff_proto_deposit_thrift, 'TimestampedChange'}},
Type = {struct, struct, {fistful_deposit_thrift, 'TimestampedChange'}},
Binary = ff_proto_utils:serialize(Type, marshal(timestamped_change, TimestampedChange)),
Decoded = ff_proto_utils:deserialize(Type, Binary),
?assertEqual(TimestampedChange, unmarshal(timestamped_change, Decoded)).
@ -286,7 +288,7 @@ deposit_change_adjustment_codec_test() ->
},
Change = {adjustment, Adjustment},
TimestampedChange = {ev, machinery_time:now(), Change},
Type = {struct, struct, {ff_proto_deposit_thrift, 'TimestampedChange'}},
Type = {struct, struct, {fistful_deposit_thrift, 'TimestampedChange'}},
Binary = ff_proto_utils:serialize(Type, marshal(timestamped_change, TimestampedChange)),
Decoded = ff_proto_utils:deserialize(Type, Binary),
?assertEqual(TimestampedChange, unmarshal(timestamped_change, Decoded)).

View File

@ -4,13 +4,13 @@
-export([publish_events/1]).
-include_lib("fistful_proto/include/ff_proto_deposit_thrift.hrl").
-include_lib("fistful_proto/include/ff_proto_cashflow_thrift.hrl").
-include_lib("fistful_proto/include/ff_proto_base_thrift.hrl").
-include_lib("fistful_proto/include/fistful_deposit_thrift.hrl").
-include_lib("fistful_proto/include/fistful_cashflow_thrift.hrl").
-include_lib("fistful_proto/include/fistful_fistful_base_thrift.hrl").
-include_lib("mg_proto/include/mg_proto_state_processing_thrift.hrl").
-type event() :: ff_eventsink_publisher:event(ff_deposit:event()).
-type sinkevent() :: ff_eventsink_publisher:sinkevent(ff_proto_deposit_thrift:'SinkEvent'()).
-type sinkevent() :: ff_eventsink_publisher:sinkevent(fistful_deposit_thrift:'SinkEvent'()).
%%
%% Internals

View File

@ -2,7 +2,9 @@
-behaviour(ff_woody_wrapper).
-include_lib("fistful_proto/include/ff_proto_deposit_thrift.hrl").
-include_lib("fistful_proto/include/fistful_deposit_thrift.hrl").
-include_lib("fistful_proto/include/fistful_fistful_base_thrift.hrl").
-include_lib("fistful_proto/include/fistful_fistful_thrift.hrl").
%% ff_woody_wrapper callbacks
-export([handle_function/3]).

View File

@ -3,7 +3,7 @@
%% Storage schema behaviour
-behaviour(machinery_mg_schema).
-include_lib("fistful_proto/include/ff_proto_deposit_thrift.hrl").
-include_lib("fistful_proto/include/fistful_deposit_thrift.hrl").
-include_lib("mg_proto/include/mg_proto_state_processing_thrift.hrl").
-export([get_version/1]).
@ -77,13 +77,13 @@ marshal_event(undefined = Version, TimestampedChange, Context) ->
machinery_mg_schema_generic:marshal({event, Version}, TimestampedChange, Context);
marshal_event(1, TimestampedChange, Context) ->
ThriftChange = ff_deposit_codec:marshal(timestamped_change, TimestampedChange),
Type = {struct, struct, {ff_proto_deposit_thrift, 'TimestampedChange'}},
Type = {struct, struct, {fistful_deposit_thrift, 'TimestampedChange'}},
{{bin, ff_proto_utils:serialize(Type, ThriftChange)}, Context}.
-spec unmarshal_event(machinery_mg_schema:version(), machinery_msgpack:t(), context()) -> {event(), context()}.
unmarshal_event(1, EncodedChange, Context) ->
{bin, EncodedThriftChange} = EncodedChange,
Type = {struct, struct, {ff_proto_deposit_thrift, 'TimestampedChange'}},
Type = {struct, struct, {fistful_deposit_thrift, 'TimestampedChange'}},
ThriftChange = ff_proto_utils:deserialize(Type, EncodedThriftChange),
{ff_deposit_codec:unmarshal(timestamped_change, ThriftChange), Context};
unmarshal_event(undefined = Version, EncodedChange, Context0) ->

View File

@ -4,7 +4,7 @@
-export([handle_function/3]).
-include_lib("fistful_proto/include/ff_proto_fistful_thrift.hrl").
-include_lib("fistful_proto/include/fistful_fistful_thrift.hrl").
-type options() :: undefined.

View File

@ -2,7 +2,7 @@
-behaviour(ff_codec).
-include_lib("fistful_proto/include/ff_proto_deposit_revert_adjustment_thrift.hrl").
-include_lib("fistful_proto/include/fistful_deposit_revert_adj_thrift.hrl").
-export([marshal/2]).
-export([unmarshal/2]).
@ -11,13 +11,13 @@
-spec marshal(ff_codec:type_name(), ff_codec:decoded_value()) -> ff_codec:encoded_value().
marshal(change, {created, Adjustment}) ->
{created, #dep_rev_adj_CreatedChange{adjustment = marshal(adjustment, Adjustment)}};
{created, #deposit_revert_adj_CreatedChange{adjustment = marshal(adjustment, Adjustment)}};
marshal(change, {status_changed, Status}) ->
{status_changed, #dep_rev_adj_StatusChange{status = marshal(status, Status)}};
{status_changed, #deposit_revert_adj_StatusChange{status = marshal(status, Status)}};
marshal(change, {p_transfer, TransferChange}) ->
{transfer, #dep_rev_adj_TransferChange{payload = ff_p_transfer_codec:marshal(change, TransferChange)}};
{transfer, #deposit_revert_adj_TransferChange{payload = ff_p_transfer_codec:marshal(change, TransferChange)}};
marshal(adjustment, Adjustment) ->
#dep_rev_adj_Adjustment{
#deposit_revert_adj_Adjustment{
id = marshal(id, ff_adjustment:id(Adjustment)),
status = maybe_marshal(status, ff_adjustment:status(Adjustment)),
changes_plan = marshal(changes_plan, ff_adjustment:changes_plan(Adjustment)),
@ -28,13 +28,13 @@ marshal(adjustment, Adjustment) ->
external_id = maybe_marshal(id, ff_adjustment:external_id(Adjustment))
};
marshal(adjustment_params, Params) ->
#dep_rev_adj_AdjustmentParams{
#deposit_revert_adj_AdjustmentParams{
id = marshal(id, maps:get(id, Params)),
change = marshal(change_request, maps:get(change, Params)),
external_id = maybe_marshal(id, maps:get(external_id, Params, undefined))
};
marshal(adjustment_state, Adjustment) ->
#dep_rev_adj_AdjustmentState{
#deposit_revert_adj_AdjustmentState{
id = marshal(id, ff_adjustment:id(Adjustment)),
status = maybe_marshal(status, ff_adjustment:status(Adjustment)),
changes_plan = marshal(changes_plan, ff_adjustment:changes_plan(Adjustment)),
@ -45,79 +45,79 @@ marshal(adjustment_state, Adjustment) ->
external_id = maybe_marshal(id, ff_adjustment:external_id(Adjustment))
};
marshal(status, pending) ->
{pending, #dep_rev_adj_Pending{}};
{pending, #deposit_revert_adj_Pending{}};
marshal(status, succeeded) ->
{succeeded, #dep_rev_adj_Succeeded{}};
{succeeded, #deposit_revert_adj_Succeeded{}};
marshal(changes_plan, Plan) ->
#dep_rev_adj_ChangesPlan{
#deposit_revert_adj_ChangesPlan{
new_cash_flow = maybe_marshal(cash_flow_change_plan, maps:get(new_cash_flow, Plan, undefined)),
new_status = maybe_marshal(status_change_plan, maps:get(new_status, Plan, undefined))
};
marshal(cash_flow_change_plan, Plan) ->
OldCashFLow = ff_cash_flow_codec:marshal(final_cash_flow, maps:get(old_cash_flow_inverted, Plan)),
NewCashFlow = ff_cash_flow_codec:marshal(final_cash_flow, maps:get(new_cash_flow, Plan)),
#dep_rev_adj_CashFlowChangePlan{
#deposit_revert_adj_CashFlowChangePlan{
old_cash_flow_inverted = OldCashFLow,
new_cash_flow = NewCashFlow
};
marshal(status_change_plan, Plan) ->
#dep_rev_adj_StatusChangePlan{
#deposit_revert_adj_StatusChangePlan{
new_status = ff_deposit_revert_status_codec:marshal(status, maps:get(new_status, Plan))
};
marshal(change_request, {change_status, Status}) ->
{change_status, #dep_rev_adj_ChangeStatusRequest{
{change_status, #deposit_revert_adj_ChangeStatusRequest{
new_status = ff_deposit_revert_status_codec:marshal(status, Status)
}};
marshal(T, V) ->
ff_codec:marshal(T, V).
-spec unmarshal(ff_codec:type_name(), ff_codec:encoded_value()) -> ff_codec:decoded_value().
unmarshal(change, {created, #dep_rev_adj_CreatedChange{adjustment = Adjustment}}) ->
unmarshal(change, {created, #deposit_revert_adj_CreatedChange{adjustment = Adjustment}}) ->
{created, unmarshal(adjustment, Adjustment)};
unmarshal(change, {status_changed, #dep_rev_adj_StatusChange{status = Status}}) ->
unmarshal(change, {status_changed, #deposit_revert_adj_StatusChange{status = Status}}) ->
{status_changed, unmarshal(status, Status)};
unmarshal(change, {transfer, #dep_rev_adj_TransferChange{payload = TransferChange}}) ->
unmarshal(change, {transfer, #deposit_revert_adj_TransferChange{payload = TransferChange}}) ->
{p_transfer, ff_p_transfer_codec:unmarshal(change, TransferChange)};
unmarshal(adjustment, Adjustment) ->
#{
id => unmarshal(id, Adjustment#dep_rev_adj_Adjustment.id),
status => unmarshal(status, Adjustment#dep_rev_adj_Adjustment.status),
changes_plan => unmarshal(changes_plan, Adjustment#dep_rev_adj_Adjustment.changes_plan),
created_at => unmarshal(timestamp_ms, Adjustment#dep_rev_adj_Adjustment.created_at),
domain_revision => unmarshal(domain_revision, Adjustment#dep_rev_adj_Adjustment.domain_revision),
party_revision => unmarshal(party_revision, Adjustment#dep_rev_adj_Adjustment.party_revision),
operation_timestamp => unmarshal(timestamp_ms, Adjustment#dep_rev_adj_Adjustment.operation_timestamp),
external_id => maybe_unmarshal(id, Adjustment#dep_rev_adj_Adjustment.external_id)
id => unmarshal(id, Adjustment#deposit_revert_adj_Adjustment.id),
status => unmarshal(status, Adjustment#deposit_revert_adj_Adjustment.status),
changes_plan => unmarshal(changes_plan, Adjustment#deposit_revert_adj_Adjustment.changes_plan),
created_at => unmarshal(timestamp_ms, Adjustment#deposit_revert_adj_Adjustment.created_at),
domain_revision => unmarshal(domain_revision, Adjustment#deposit_revert_adj_Adjustment.domain_revision),
party_revision => unmarshal(party_revision, Adjustment#deposit_revert_adj_Adjustment.party_revision),
operation_timestamp => unmarshal(timestamp_ms, Adjustment#deposit_revert_adj_Adjustment.operation_timestamp),
external_id => maybe_unmarshal(id, Adjustment#deposit_revert_adj_Adjustment.external_id)
};
unmarshal(adjustment_params, Params) ->
genlib_map:compact(#{
id => unmarshal(id, Params#dep_rev_adj_AdjustmentParams.id),
change => unmarshal(change_request, Params#dep_rev_adj_AdjustmentParams.change),
external_id => maybe_unmarshal(id, Params#dep_rev_adj_AdjustmentParams.external_id)
id => unmarshal(id, Params#deposit_revert_adj_AdjustmentParams.id),
change => unmarshal(change_request, Params#deposit_revert_adj_AdjustmentParams.change),
external_id => maybe_unmarshal(id, Params#deposit_revert_adj_AdjustmentParams.external_id)
});
unmarshal(status, {pending, #dep_rev_adj_Pending{}}) ->
unmarshal(status, {pending, #deposit_revert_adj_Pending{}}) ->
pending;
unmarshal(status, {succeeded, #dep_rev_adj_Succeeded{}}) ->
unmarshal(status, {succeeded, #deposit_revert_adj_Succeeded{}}) ->
succeeded;
unmarshal(changes_plan, Plan) ->
genlib_map:compact(#{
new_cash_flow => maybe_unmarshal(cash_flow_change_plan, Plan#dep_rev_adj_ChangesPlan.new_cash_flow),
new_status => maybe_unmarshal(status_change_plan, Plan#dep_rev_adj_ChangesPlan.new_status)
new_cash_flow => maybe_unmarshal(cash_flow_change_plan, Plan#deposit_revert_adj_ChangesPlan.new_cash_flow),
new_status => maybe_unmarshal(status_change_plan, Plan#deposit_revert_adj_ChangesPlan.new_status)
});
unmarshal(cash_flow_change_plan, Plan) ->
OldCashFlow = Plan#dep_rev_adj_CashFlowChangePlan.old_cash_flow_inverted,
NewCashFlow = Plan#dep_rev_adj_CashFlowChangePlan.new_cash_flow,
OldCashFlow = Plan#deposit_revert_adj_CashFlowChangePlan.old_cash_flow_inverted,
NewCashFlow = Plan#deposit_revert_adj_CashFlowChangePlan.new_cash_flow,
#{
old_cash_flow_inverted => ff_cash_flow_codec:unmarshal(final_cash_flow, OldCashFlow),
new_cash_flow => ff_cash_flow_codec:unmarshal(final_cash_flow, NewCashFlow)
};
unmarshal(status_change_plan, Plan) ->
Status = Plan#dep_rev_adj_StatusChangePlan.new_status,
Status = Plan#deposit_revert_adj_StatusChangePlan.new_status,
#{
new_status => ff_deposit_revert_status_codec:unmarshal(status, Status)
};
unmarshal(change_request, {change_status, Request}) ->
Status = Request#dep_rev_adj_ChangeStatusRequest.new_status,
Status = Request#deposit_revert_adj_ChangeStatusRequest.new_status,
{change_status, ff_deposit_revert_status_codec:unmarshal(status, Status)};
unmarshal(T, V) ->
ff_codec:unmarshal(T, V).

View File

@ -2,7 +2,11 @@
-behaviour(ff_codec).
-include_lib("fistful_proto/include/ff_proto_deposit_revert_thrift.hrl").
-include_lib("fistful_proto/include/fistful_deposit_revert_thrift.hrl").
-include_lib("fistful_proto/include/fistful_fistful_base_thrift.hrl").
-include_lib("fistful_proto/include/fistful_deposit_revert_status_thrift.hrl").
-include_lib("fistful_proto/include/fistful_deposit_revert_adj_thrift.hrl").
-include_lib("fistful_proto/include/fistful_cashflow_thrift.hrl").
-export([marshal/2]).
-export([unmarshal/2]).
@ -143,7 +147,7 @@ revert_symmetry_test() ->
created_at = <<"2000-01-01T00:00:00Z">>,
external_id = undefined,
reason = <<"why not">>,
status = {pending, #dep_rev_status_Pending{}},
status = {pending, #deposit_revert_status_Pending{}},
id = genlib:unique()
},
?assertEqual(Encoded, marshal(revert, unmarshal(revert, Encoded))).
@ -167,12 +171,12 @@ change_adjustment_symmetry_test() ->
{adjustment, #deposit_revert_AdjustmentChange{
id = genlib:unique(),
payload =
{created, #dep_rev_adj_CreatedChange{
adjustment = #dep_rev_adj_Adjustment{
{created, #deposit_revert_adj_CreatedChange{
adjustment = #deposit_revert_adj_Adjustment{
id = genlib:unique(),
status = {pending, #dep_rev_adj_Pending{}},
changes_plan = #dep_rev_adj_ChangesPlan{
new_cash_flow = #dep_rev_adj_CashFlowChangePlan{
status = {pending, #deposit_revert_adj_Pending{}},
changes_plan = #deposit_revert_adj_ChangesPlan{
new_cash_flow = #deposit_revert_adj_CashFlowChangePlan{
old_cash_flow_inverted = #cashflow_FinalCashFlow{postings = []},
new_cash_flow = #cashflow_FinalCashFlow{postings = []}
}

View File

@ -2,7 +2,7 @@
-behaviour(ff_codec).
-include_lib("fistful_proto/include/ff_proto_deposit_revert_status_thrift.hrl").
-include_lib("fistful_proto/include/fistful_deposit_revert_status_thrift.hrl").
-export([marshal/2]).
-export([unmarshal/2]).
@ -11,20 +11,20 @@
-spec marshal(ff_codec:type_name(), ff_codec:decoded_value()) -> ff_codec:encoded_value().
marshal(status, pending) ->
{pending, #dep_rev_status_Pending{}};
{pending, #deposit_revert_status_Pending{}};
marshal(status, succeeded) ->
{succeeded, #dep_rev_status_Succeeded{}};
{succeeded, #deposit_revert_status_Succeeded{}};
marshal(status, {failed, Failure}) ->
{failed, #dep_rev_status_Failed{failure = marshal(failure, Failure)}};
{failed, #deposit_revert_status_Failed{failure = marshal(failure, Failure)}};
marshal(T, V) ->
ff_codec:marshal(T, V).
-spec unmarshal(ff_codec:type_name(), ff_codec:encoded_value()) -> ff_codec:decoded_value().
unmarshal(status, {pending, #dep_rev_status_Pending{}}) ->
unmarshal(status, {pending, #deposit_revert_status_Pending{}}) ->
pending;
unmarshal(status, {succeeded, #dep_rev_status_Succeeded{}}) ->
unmarshal(status, {succeeded, #deposit_revert_status_Succeeded{}}) ->
succeeded;
unmarshal(status, {failed, #dep_rev_status_Failed{failure = Failure}}) ->
unmarshal(status, {failed, #deposit_revert_status_Failed{failure = Failure}}) ->
{failed, unmarshal(failure, Failure)};
unmarshal(T, V) ->
ff_codec:unmarshal(T, V).

View File

@ -2,7 +2,7 @@
-behaviour(ff_codec).
-include_lib("fistful_proto/include/ff_proto_deposit_status_thrift.hrl").
-include_lib("fistful_proto/include/fistful_deposit_status_thrift.hrl").
-export([marshal/2]).
-export([unmarshal/2]).
@ -11,20 +11,20 @@
-spec marshal(ff_codec:type_name(), ff_codec:decoded_value()) -> ff_codec:encoded_value().
marshal(status, pending) ->
{pending, #dep_status_Pending{}};
{pending, #deposit_status_Pending{}};
marshal(status, succeeded) ->
{succeeded, #dep_status_Succeeded{}};
{succeeded, #deposit_status_Succeeded{}};
marshal(status, {failed, Failure}) ->
{failed, #dep_status_Failed{failure = marshal(failure, Failure)}};
{failed, #deposit_status_Failed{failure = marshal(failure, Failure)}};
marshal(T, V) ->
ff_codec:marshal(T, V).
-spec unmarshal(ff_codec:type_name(), ff_codec:encoded_value()) -> ff_codec:decoded_value().
unmarshal(status, {pending, #dep_status_Pending{}}) ->
unmarshal(status, {pending, #deposit_status_Pending{}}) ->
pending;
unmarshal(status, {succeeded, #dep_status_Succeeded{}}) ->
unmarshal(status, {succeeded, #deposit_status_Succeeded{}}) ->
succeeded;
unmarshal(status, {failed, #dep_status_Failed{failure = Failure}}) ->
unmarshal(status, {failed, #deposit_status_Failed{failure = Failure}}) ->
{failed, unmarshal(failure, Failure)};
unmarshal(T, V) ->
ff_codec:unmarshal(T, V).

View File

@ -2,7 +2,7 @@
-behaviour(ff_codec).
-include_lib("fistful_proto/include/ff_proto_destination_thrift.hrl").
-include_lib("fistful_proto/include/fistful_destination_thrift.hrl").
-export([unmarshal_destination_params/1]).
-export([marshal_destination_state/2]).
@ -14,20 +14,20 @@
%% API
-spec unmarshal_destination_params(ff_proto_destination_thrift:'DestinationParams'()) -> ff_destination:params().
-spec unmarshal_destination_params(fistful_destination_thrift:'DestinationParams'()) -> ff_destination:params().
unmarshal_destination_params(Params) ->
genlib_map:compact(#{
id => unmarshal(id, Params#dst_DestinationParams.id),
identity => unmarshal(id, Params#dst_DestinationParams.identity),
name => unmarshal(string, Params#dst_DestinationParams.name),
currency => unmarshal(string, Params#dst_DestinationParams.currency),
resource => unmarshal(resource, Params#dst_DestinationParams.resource),
external_id => maybe_unmarshal(id, Params#dst_DestinationParams.external_id),
metadata => maybe_unmarshal(ctx, Params#dst_DestinationParams.metadata)
id => unmarshal(id, Params#destination_DestinationParams.id),
identity => unmarshal(id, Params#destination_DestinationParams.identity),
name => unmarshal(string, Params#destination_DestinationParams.name),
currency => unmarshal(string, Params#destination_DestinationParams.currency),
resource => unmarshal(resource, Params#destination_DestinationParams.resource),
external_id => maybe_unmarshal(id, Params#destination_DestinationParams.external_id),
metadata => maybe_unmarshal(ctx, Params#destination_DestinationParams.metadata)
}).
-spec marshal_destination_state(ff_destination:destination_state(), ff_entity_context:context()) ->
ff_proto_destination_thrift:'DestinationState'().
fistful_destination_thrift:'DestinationState'().
marshal_destination_state(DestinationState, Context) ->
Blocking =
case ff_destination:is_accessible(DestinationState) of
@ -36,7 +36,7 @@ marshal_destination_state(DestinationState, Context) ->
_ ->
blocked
end,
#dst_DestinationState{
#destination_DestinationState{
id = marshal(id, ff_destination:id(DestinationState)),
name = marshal(string, ff_destination:name(DestinationState)),
resource = maybe_marshal(resource, ff_destination:resource(DestinationState)),
@ -49,9 +49,9 @@ marshal_destination_state(DestinationState, Context) ->
context = maybe_marshal(ctx, Context)
}.
-spec marshal_event(ff_destination_machine:event()) -> ff_proto_destination_thrift:'Event'().
-spec marshal_event(ff_destination_machine:event()) -> fistful_destination_thrift:'Event'().
marshal_event({EventID, {ev, Timestamp, Change}}) ->
#dst_Event{
#destination_Event{
event_id = ff_codec:marshal(event_id, EventID),
occured_at = ff_codec:marshal(timestamp, Timestamp),
change = marshal(change, Change)
@ -59,7 +59,7 @@ marshal_event({EventID, {ev, Timestamp, Change}}) ->
-spec marshal(ff_codec:type_name(), ff_codec:decoded_value()) -> ff_codec:encoded_value().
marshal(timestamped_change, {ev, Timestamp, Change}) ->
#dst_TimestampedChange{
#destination_TimestampedChange{
change = marshal(change, Change),
occured_at = ff_codec:marshal(timestamp, Timestamp)
};
@ -76,7 +76,7 @@ marshal(
resource := Resource
}
) ->
#dst_Destination{
#destination_Destination{
name = Name,
resource = marshal(resource, Resource),
created_at = maybe_marshal(timestamp_ms, maps:get(created_at, Destination, undefined)),
@ -84,13 +84,13 @@ marshal(
metadata = maybe_marshal(ctx, maps:get(metadata, Destination, undefined))
};
marshal(status, authorized) ->
{authorized, #dst_Authorized{}};
{authorized, #destination_Authorized{}};
marshal(status, unauthorized) ->
{unauthorized, #dst_Unauthorized{}};
{unauthorized, #destination_Unauthorized{}};
marshal(status_change, unauthorized) ->
{changed, {unauthorized, #dst_Unauthorized{}}};
{changed, {unauthorized, #destination_Unauthorized{}}};
marshal(status_change, authorized) ->
{changed, {authorized, #dst_Authorized{}}};
{changed, {authorized, #destination_Authorized{}}};
marshal(ctx, Ctx) ->
marshal(context, Ctx);
marshal(T, V) ->
@ -99,15 +99,15 @@ marshal(T, V) ->
-spec unmarshal(ff_codec:type_name(), ff_codec:encoded_value()) -> ff_codec:decoded_value().
unmarshal({list, T}, V) ->
[unmarshal(T, E) || E <- V];
unmarshal(repair_scenario, {add_events, #dst_AddEventsRepair{events = Events, action = Action}}) ->
unmarshal(repair_scenario, {add_events, #destination_AddEventsRepair{events = Events, action = Action}}) ->
{add_events,
genlib_map:compact(#{
events => unmarshal({list, change}, Events),
action => maybe_unmarshal(complex_action, Action)
})};
unmarshal(timestamped_change, TimestampedChange) ->
Timestamp = ff_codec:unmarshal(timestamp, TimestampedChange#dst_TimestampedChange.occured_at),
Change = unmarshal(change, TimestampedChange#dst_TimestampedChange.change),
Timestamp = ff_codec:unmarshal(timestamp, TimestampedChange#destination_TimestampedChange.occured_at),
Change = unmarshal(change, TimestampedChange#destination_TimestampedChange.change),
{ev, Timestamp, Change};
unmarshal(change, {created, Destination}) ->
{created, unmarshal(destination, Destination)};
@ -118,19 +118,19 @@ unmarshal(change, {status, StatusChange}) ->
unmarshal(destination, Dest) ->
genlib_map:compact(#{
version => 3,
resource => unmarshal(resource, Dest#dst_Destination.resource),
name => unmarshal(string, Dest#dst_Destination.name),
created_at => maybe_unmarshal(timestamp_ms, Dest#dst_Destination.created_at),
external_id => maybe_unmarshal(id, Dest#dst_Destination.external_id),
metadata => maybe_unmarshal(ctx, Dest#dst_Destination.metadata)
resource => unmarshal(resource, Dest#destination_Destination.resource),
name => unmarshal(string, Dest#destination_Destination.name),
created_at => maybe_unmarshal(timestamp_ms, Dest#destination_Destination.created_at),
external_id => maybe_unmarshal(id, Dest#destination_Destination.external_id),
metadata => maybe_unmarshal(ctx, Dest#destination_Destination.metadata)
});
unmarshal(status, {authorized, #dst_Authorized{}}) ->
unmarshal(status, {authorized, #destination_Authorized{}}) ->
authorized;
unmarshal(status, {unauthorized, #dst_Unauthorized{}}) ->
unmarshal(status, {unauthorized, #destination_Unauthorized{}}) ->
unauthorized;
unmarshal(status_change, {changed, {unauthorized, #dst_Unauthorized{}}}) ->
unmarshal(status_change, {changed, {unauthorized, #destination_Unauthorized{}}}) ->
unauthorized;
unmarshal(status_change, {changed, {authorized, #dst_Authorized{}}}) ->
unmarshal(status_change, {changed, {authorized, #destination_Authorized{}}}) ->
authorized;
unmarshal(ctx, Ctx) ->
maybe_unmarshal(context, Ctx);

View File

@ -4,10 +4,10 @@
-export([publish_events/1]).
-include_lib("fistful_proto/include/ff_proto_destination_thrift.hrl").
-include_lib("fistful_proto/include/fistful_destination_thrift.hrl").
-type event() :: ff_eventsink_publisher:event(ff_destination:event()).
-type sinkevent() :: ff_eventsink_publisher:sinkevent(ff_proto_destination_thrift:'SinkEvent'()).
-type sinkevent() :: ff_eventsink_publisher:sinkevent(fistful_destination_thrift:'SinkEvent'()).
-spec publish_events(list(event())) -> list(sinkevent()).
publish_events(Events) ->
@ -23,11 +23,11 @@ publish_event(#{
{ev, EventDt, Payload}
}
}) ->
#dst_SinkEvent{
#destination_SinkEvent{
id = marshal(event_id, ID),
created_at = marshal(timestamp, Dt),
source = marshal(id, SourceID),
payload = #dst_EventSinkPayload{
payload = #destination_EventSinkPayload{
sequence = marshal(event_id, EventID),
occured_at = marshal(timestamp, EventDt),
changes = [marshal(change, Payload)]

View File

@ -2,7 +2,9 @@
-behaviour(ff_woody_wrapper).
-include_lib("fistful_proto/include/ff_proto_destination_thrift.hrl").
-include_lib("fistful_proto/include/fistful_destination_thrift.hrl").
-include_lib("fistful_proto/include/fistful_fistful_base_thrift.hrl").
-include_lib("fistful_proto/include/fistful_fistful_thrift.hrl").
%% ff_woody_wrapper callbacks
-export([handle_function/3]).
@ -24,7 +26,7 @@ handle_function(Func, Args, Opts) ->
%% Internals
%%
handle_function_('Create', {Params, Ctx}, Opts) ->
ID = Params#dst_DestinationParams.id,
ID = Params#destination_DestinationParams.id,
case
ff_destination_machine:create(
ff_destination_codec:unmarshal_destination_params(Params),

View File

@ -3,7 +3,7 @@
%% Storage schema behaviour
-behaviour(machinery_mg_schema).
-include_lib("fistful_proto/include/ff_proto_destination_thrift.hrl").
-include_lib("fistful_proto/include/fistful_destination_thrift.hrl").
-include_lib("mg_proto/include/mg_proto_state_processing_thrift.hrl").
%% Constants
@ -78,13 +78,13 @@ marshal_event(undefined = Version, TimestampedChange, Context) ->
%%======
marshal_event(1, TimestampedChange, Context) ->
ThriftChange = ff_destination_codec:marshal(timestamped_change, TimestampedChange),
Type = {struct, struct, {ff_proto_destination_thrift, 'TimestampedChange'}},
Type = {struct, struct, {fistful_destination_thrift, 'TimestampedChange'}},
{{bin, ff_proto_utils:serialize(Type, ThriftChange)}, Context}.
-spec unmarshal_event(machinery_mg_schema:version(), machinery_msgpack:t(), context()) -> {event(), context()}.
unmarshal_event(1, EncodedChange, Context) ->
{bin, EncodedThriftChange} = EncodedChange,
Type = {struct, struct, {ff_proto_destination_thrift, 'TimestampedChange'}},
Type = {struct, struct, {fistful_destination_thrift, 'TimestampedChange'}},
ThriftChange = ff_proto_utils:deserialize(Type, EncodedThriftChange),
{ff_destination_codec:unmarshal(timestamped_change, ThriftChange), Context};
unmarshal_event(undefined = Version, EncodedChange, Context0) ->

View File

@ -1,6 +1,6 @@
-module(ff_entity_context_codec).
-include_lib("fistful_proto/include/ff_proto_msgpack_thrift.hrl").
-include_lib("fistful_proto/include/fistful_msgp_thrift.hrl").
-type ctx() :: ff_entity_context:context().

View File

@ -4,7 +4,7 @@
-export([handle_function/3]).
-include_lib("fistful_proto/include/ff_proto_eventsink_thrift.hrl").
-include_lib("fistful_proto/include/fistful_evsink_thrift.hrl").
-type options() :: #{
schema := module(),

View File

@ -2,7 +2,7 @@
-behaviour(ff_codec).
-include_lib("fistful_proto/include/ff_proto_identity_thrift.hrl").
-include_lib("fistful_proto/include/fistful_identity_thrift.hrl").
-export([unmarshal_identity_params/1]).
@ -13,8 +13,8 @@
-export([unmarshal/2]).
%% This special functions hasn't got opposite functions.
-spec unmarshal_identity_params(ff_proto_identity_thrift:'IdentityParams'()) -> ff_identity_machine:params().
unmarshal_identity_params(#idnt_IdentityParams{
-spec unmarshal_identity_params(fistful_identity_thrift:'IdentityParams'()) -> ff_identity_machine:params().
unmarshal_identity_params(#identity_IdentityParams{
id = ID,
name = Name,
party = PartyID,
@ -32,18 +32,18 @@ unmarshal_identity_params(#idnt_IdentityParams{
}).
-spec marshal_identity_event({integer(), ff_machine:timestamped_event(ff_identity:event())}) ->
ff_proto_identity_thrift:'Event'().
fistful_identity_thrift:'Event'().
marshal_identity_event({ID, {ev, Timestamp, Ev}}) ->
#idnt_Event{
#identity_Event{
sequence = marshal(event_id, ID),
occured_at = marshal(timestamp, Timestamp),
change = marshal(change, Ev)
}.
-spec marshal_identity_state(ff_identity:identity_state(), ff_entity_context:context()) ->
ff_proto_identity_thrift:'IdentityState'().
fistful_identity_thrift:'IdentityState'().
marshal_identity_state(IdentityState, Context) ->
#idnt_IdentityState{
#identity_IdentityState{
id = maybe_marshal(id, ff_identity:id(IdentityState)),
name = marshal(string, ff_identity:name(IdentityState)),
party_id = marshal(id, ff_identity:party(IdentityState)),
@ -60,14 +60,14 @@ marshal_identity_state(IdentityState, Context) ->
marshal({list, T}, V) ->
[marshal(T, E) || E <- V];
marshal(timestamped_change, {ev, Timestamp, Change}) ->
#idnt_TimestampedChange{
#identity_TimestampedChange{
change = marshal(change, Change),
occured_at = ff_codec:marshal(timestamp, Timestamp)
};
marshal(change, {created, Identity}) ->
{created, marshal(identity, Identity)};
marshal(identity, Identity) ->
#idnt_Identity{
#identity_Identity{
id = maybe_marshal(id, ff_identity:id(Identity)),
name = maybe_marshal(string, ff_identity:name(Identity)),
party = marshal(id, ff_identity:party(Identity)),
@ -92,10 +92,10 @@ marshal(T, V) ->
unmarshal({list, T}, V) ->
[unmarshal(T, E) || E <- V];
unmarshal(timestamped_change, TimestampedChange) ->
Timestamp = ff_codec:unmarshal(timestamp, TimestampedChange#idnt_TimestampedChange.occured_at),
Change = unmarshal(change, TimestampedChange#idnt_TimestampedChange.change),
Timestamp = ff_codec:unmarshal(timestamp, TimestampedChange#identity_TimestampedChange.occured_at),
Change = unmarshal(change, TimestampedChange#identity_TimestampedChange.change),
{ev, Timestamp, Change};
unmarshal(repair_scenario, {add_events, #idnt_AddEventsRepair{events = Events, action = Action}}) ->
unmarshal(repair_scenario, {add_events, #identity_AddEventsRepair{events = Events, action = Action}}) ->
{add_events,
genlib_map:compact(#{
events => unmarshal({list, change}, Events),
@ -106,11 +106,11 @@ unmarshal(change, {created, Identity}) ->
% We have to support this unmarshal cause mg contain identety's events with challenge
unmarshal(change, {level_changed, LevelID}) ->
{level_changed, unmarshal(id, LevelID)};
unmarshal(change, {identity_challenge, #idnt_ChallengeChange{id = ID, payload = Payload}}) ->
unmarshal(change, {identity_challenge, #identity_ChallengeChange{id = ID, payload = Payload}}) ->
{{challenge, unmarshal(id, ID)}, unmarshal(challenge_payload, Payload)};
unmarshal(change, {effective_challenge_changed, ChallengeID}) ->
{effective_challenge_changed, unmarshal(id, ChallengeID)};
unmarshal(identity, #idnt_Identity{
unmarshal(identity, #identity_Identity{
id = ID,
name = Name,
party = PartyID,
@ -135,7 +135,7 @@ unmarshal(challenge_payload, {created, Challenge}) ->
{created, unmarshal(challenge_payload_created, Challenge)};
unmarshal(challenge_payload, {status_changed, ChallengeStatus}) ->
{status_changed, unmarshal(challenge_payload_status_changed, ChallengeStatus)};
unmarshal(challenge_payload_created, #idnt_Challenge{
unmarshal(challenge_payload_created, #identity_Challenge{
id = ID,
cls = ChallengeClass,
provider_id = ProviderID,
@ -157,20 +157,20 @@ unmarshal(challenge_payload_created, #idnt_Challenge{
};
unmarshal(challenge_proofs, Proof) ->
{
unmarshal(proof_type, Proof#idnt_ChallengeProof.type),
unmarshal(id, Proof#idnt_ChallengeProof.token)
unmarshal(proof_type, Proof#identity_ChallengeProof.type),
unmarshal(id, Proof#identity_ChallengeProof.token)
};
unmarshal(proof_type, rus_domestic_passport) ->
rus_domestic_passport;
unmarshal(proof_type, rus_retiree_insurance_cert) ->
rus_retiree_insurance_cert;
unmarshal(challenge_payload_status_changed, {pending, #idnt_ChallengePending{}}) ->
unmarshal(challenge_payload_status_changed, {pending, #identity_ChallengePending{}}) ->
pending;
unmarshal(challenge_payload_status_changed, {cancelled, #idnt_ChallengeCancelled{}}) ->
unmarshal(challenge_payload_status_changed, {cancelled, #identity_ChallengeCancelled{}}) ->
cancelled;
unmarshal(
challenge_payload_status_changed,
{completed, #idnt_ChallengeCompleted{
{completed, #identity_ChallengeCompleted{
resolution = Resolution,
valid_until = ValidUntil
}}
@ -180,7 +180,7 @@ unmarshal(
resolution => unmarshal(resolution, Resolution),
valid_until => maybe_unmarshal(timestamp, ValidUntil)
})};
unmarshal(challenge_payload_status_changed, {failed, #idnt_ChallengeFailed{}}) ->
unmarshal(challenge_payload_status_changed, {failed, #identity_ChallengeFailed{}}) ->
% FIXME: Describe failures in protocol
{failed, unknown};
unmarshal(resolution, approved) ->

View File

@ -4,10 +4,10 @@
-export([publish_events/1]).
-include_lib("fistful_proto/include/ff_proto_identity_thrift.hrl").
-include_lib("fistful_proto/include/fistful_identity_thrift.hrl").
-type event() :: ff_eventsink_publisher:event(ff_identity:event()).
-type sinkevent() :: ff_eventsink_publisher:sinkevent(ff_proto_identity_thrift:'SinkEvent'()).
-type sinkevent() :: ff_eventsink_publisher:sinkevent(fistful_identity_thrift:'SinkEvent'()).
-spec publish_events(list(event())) -> list(sinkevent()).
publish_events(Events) ->
@ -23,11 +23,11 @@ publish_event(#{
{ev, EventDt, Payload}
}
}) ->
#idnt_SinkEvent{
#identity_SinkEvent{
id = marshal(event_id, ID),
created_at = marshal(timestamp, Dt),
source = marshal(id, SourceID),
payload = #idnt_EventSinkPayload{
payload = #identity_EventSinkPayload{
sequence = marshal(event_id, EventID),
occured_at = marshal(timestamp, EventDt),
changes = [marshal(change, Payload)]

View File

@ -2,7 +2,9 @@
-behaviour(ff_woody_wrapper).
-include_lib("fistful_proto/include/ff_proto_identity_thrift.hrl").
-include_lib("fistful_proto/include/fistful_identity_thrift.hrl").
-include_lib("fistful_proto/include/fistful_fistful_base_thrift.hrl").
-include_lib("fistful_proto/include/fistful_fistful_thrift.hrl").
%% ff_woody_wrapper callbacks
-export([handle_function/3]).

View File

@ -3,7 +3,7 @@
%% Storage schema behaviour
-behaviour(machinery_mg_schema).
-include_lib("fistful_proto/include/ff_proto_identity_thrift.hrl").
-include_lib("fistful_proto/include/fistful_identity_thrift.hrl").
-include_lib("mg_proto/include/mg_proto_state_processing_thrift.hrl").
-export([get_version/1]).
@ -28,8 +28,8 @@
-type legacy_change() :: any().
-type timestamped_change() :: ff_proto_identity_thrift:'TimestampedChange'().
-type thrift_change() :: ff_proto_identity_thrift:'Change'().
-type timestamped_change() :: fistful_identity_thrift:'TimestampedChange'().
-type thrift_change() :: fistful_identity_thrift:'Change'().
-type data() ::
aux_state()
@ -83,7 +83,7 @@ marshal_event(undefined = Version, TimestampedChange, Context) ->
machinery_mg_schema_generic:marshal({event, Version}, TimestampedChange, Context);
marshal_event(Version, TimestampedChange, Context) when Version =:= 1; Version =:= 2 ->
ThriftChange = ff_identity_codec:marshal(timestamped_change, TimestampedChange),
Type = {struct, struct, {ff_proto_identity_thrift, 'TimestampedChange'}},
Type = {struct, struct, {fistful_identity_thrift, 'TimestampedChange'}},
{{bin, ff_proto_utils:serialize(Type, ThriftChange)}, Context}.
-spec unmarshal_event(machinery_mg_schema:version(), machinery_msgpack:t(), context()) -> {event(), context()}.
@ -92,8 +92,8 @@ unmarshal_event(2, EncodedChange, Context) ->
{ff_identity_codec:unmarshal(timestamped_change, ThriftChange), Context};
unmarshal_event(1, EncodedChange, Context) ->
ThriftChange = unmashal_thrift_change(EncodedChange),
MigratedChange = ThriftChange#idnt_TimestampedChange{
change = maybe_migrate_thrift_change(ThriftChange#idnt_TimestampedChange.change, Context)
MigratedChange = ThriftChange#identity_TimestampedChange{
change = maybe_migrate_thrift_change(ThriftChange#identity_TimestampedChange.change, Context)
},
{ff_identity_codec:unmarshal(timestamped_change, MigratedChange), Context};
unmarshal_event(undefined = Version, EncodedChange, Context) ->
@ -107,13 +107,13 @@ unmarshal_event(undefined = Version, EncodedChange, Context) ->
-spec unmashal_thrift_change(machinery_msgpack:t()) -> timestamped_change().
unmashal_thrift_change(EncodedChange) ->
{bin, EncodedThriftChange} = EncodedChange,
Type = {struct, struct, {ff_proto_identity_thrift, 'TimestampedChange'}},
Type = {struct, struct, {fistful_identity_thrift, 'TimestampedChange'}},
ff_proto_utils:deserialize(Type, EncodedThriftChange).
-spec maybe_migrate_thrift_change(thrift_change(), context()) -> thrift_change().
maybe_migrate_thrift_change({created, #idnt_Identity{name = undefined} = Identity}, MigrateContext) ->
Context = fetch_entity_context(Identity#idnt_Identity.id, MigrateContext),
{created, Identity#idnt_Identity{name = get_legacy_name(Context)}};
maybe_migrate_thrift_change({created, #identity_Identity{name = undefined} = Identity}, MigrateContext) ->
Context = fetch_entity_context(Identity#identity_Identity.id, MigrateContext),
{created, Identity#identity_Identity{name = get_legacy_name(Context)}};
maybe_migrate_thrift_change(Change, _MigrateContext) ->
Change.

View File

@ -2,7 +2,7 @@
-behaviour(ff_codec).
-include_lib("fistful_proto/include/ff_proto_limit_check_thrift.hrl").
-include_lib("fistful_proto/include/fistful_lim_check_thrift.hrl").
-export([marshal/2]).
-export([unmarshal/2]).

View File

@ -1,6 +1,6 @@
-module(ff_msgpack_codec).
-include_lib("fistful_proto/include/ff_proto_msgpack_thrift.hrl").
-include_lib("fistful_proto/include/fistful_msgp_thrift.hrl").
-export([unmarshal/2]).
-export([marshal/2]).
@ -17,7 +17,7 @@
| {binary, binary()}
| nil.
-type encoded_value() :: ff_proto_msgpack_thrift:'Value'().
-type encoded_value() :: fistful_msgp_thrift:'Value'().
-export_type([type_name/0]).
-export_type([encoded_value/0]).

View File

@ -2,9 +2,9 @@
-behaviour(ff_codec).
-include_lib("fistful_proto/include/ff_proto_base_thrift.hrl").
-include_lib("fistful_proto/include/ff_proto_transfer_thrift.hrl").
-include_lib("fistful_proto/include/ff_proto_cashflow_thrift.hrl").
-include_lib("fistful_proto/include/fistful_fistful_base_thrift.hrl").
-include_lib("fistful_proto/include/fistful_transfer_thrift.hrl").
-include_lib("fistful_proto/include/fistful_cashflow_thrift.hrl").
-export([marshal/2]).
-export([unmarshal/2]).

View File

@ -2,7 +2,8 @@
-behaviour(ff_woody_wrapper).
-include_lib("fistful_proto/include/ff_proto_provider_thrift.hrl").
-include_lib("fistful_proto/include/fistful_provider_thrift.hrl").
-include_lib("fistful_proto/include/fistful_fistful_thrift.hrl").
%% ff_woody_wrapper callbacks
-export([handle_function/3]).
@ -37,11 +38,11 @@ handle_function_('ListProviders', _, _Opts) ->
%%
-spec marshal_providers([ff_provider:provider()]) -> [ff_proto_provider_thrift:'Provider'()].
-spec marshal_providers([ff_provider:provider()]) -> [fistful_provider_thrift:'Provider'()].
marshal_providers(Providers) when is_list(Providers) ->
lists:map(fun(Provider) -> marshal_provider(Provider) end, Providers).
-spec marshal_provider(ff_provider:provider()) -> ff_proto_provider_thrift:'Provider'().
-spec marshal_provider(ff_provider:provider()) -> fistful_provider_thrift:'Provider'().
marshal_provider(Provider) ->
ID = ff_provider:id(Provider),
Name = ff_provider:name(Provider),

View File

@ -2,7 +2,8 @@
-behaviour(ff_woody_wrapper).
-include_lib("fistful_proto/include/ff_proto_fistful_admin_thrift.hrl").
-include_lib("fistful_proto/include/fistful_admin_thrift.hrl").
-include_lib("fistful_proto/include/fistful_fistful_thrift.hrl").
%% ff_woody_wrapper callbacks
-export([handle_function/3]).
@ -26,15 +27,15 @@ handle_function(Func, Args, Opts) ->
%%
handle_function_('CreateSource', {Params}, Opts) ->
SourceID = Params#ff_admin_SourceParams.id,
SourceID = Params#admin_SourceParams.id,
case
ff_source_machine:create(
#{
id => SourceID,
identity => Params#ff_admin_SourceParams.identity_id,
name => Params#ff_admin_SourceParams.name,
currency => ff_codec:unmarshal(currency_ref, Params#ff_admin_SourceParams.currency),
resource => ff_source_codec:unmarshal(resource, Params#ff_admin_SourceParams.resource)
identity => Params#admin_SourceParams.identity_id,
name => Params#admin_SourceParams.name,
currency => ff_codec:unmarshal(currency_ref, Params#admin_SourceParams.currency),
resource => ff_source_codec:unmarshal(resource, Params#admin_SourceParams.resource)
},
ff_entity_context:new()
)
@ -57,12 +58,12 @@ handle_function_('GetSource', {ID}, _Opts) ->
woody_error:raise(business, #fistful_SourceNotFound{})
end;
handle_function_('CreateDeposit', {Params}, Opts) ->
DepositID = Params#ff_admin_DepositParams.id,
DepositID = Params#admin_DepositParams.id,
DepositParams = #{
id => DepositID,
source_id => Params#ff_admin_DepositParams.source,
wallet_id => Params#ff_admin_DepositParams.destination,
body => ff_codec:unmarshal(cash, Params#ff_admin_DepositParams.body)
source_id => Params#admin_DepositParams.source,
wallet_id => Params#admin_DepositParams.destination,
body => ff_codec:unmarshal(cash, Params#admin_DepositParams.body)
},
case handle_create_result(ff_deposit_machine:create(DepositParams, ff_entity_context:new())) of
ok ->
@ -74,11 +75,11 @@ handle_function_('CreateDeposit', {Params}, Opts) ->
{error, {wallet, notfound}} ->
woody_error:raise(business, #fistful_DestinationNotFound{});
{error, {terms_violation, {not_allowed_currency, _More}}} ->
woody_error:raise(business, #ff_admin_DepositCurrencyInvalid{});
woody_error:raise(business, #admin_DepositCurrencyInvalid{});
{error, {inconsistent_currency, _Details}} ->
woody_error:raise(business, #ff_admin_DepositCurrencyInvalid{});
woody_error:raise(business, #admin_DepositCurrencyInvalid{});
{error, {bad_deposit_amount, _Amount}} ->
woody_error:raise(business, #ff_admin_DepositAmountInvalid{});
woody_error:raise(business, #admin_DepositAmountInvalid{});
{error, Error} ->
woody_error:raise(system, {internal, result_unexpected, woody_error:format_details(Error)})
end;

View File

@ -16,51 +16,51 @@
-spec get_service(service_name()) -> service().
get_service(fistful_admin) ->
{ff_proto_fistful_admin_thrift, 'FistfulAdmin'};
{fistful_admin_thrift, 'FistfulAdmin'};
get_service(fistful_provider) ->
{ff_proto_provider_thrift, 'Management'};
{fistful_provider_thrift, 'Management'};
get_service(ff_withdrawal_adapter_host) ->
{dmsl_withdrawals_provider_adapter_thrift, 'AdapterHost'};
{dmsl_wthd_provider_thrift, 'AdapterHost'};
get_service(deposit_event_sink) ->
{ff_proto_deposit_thrift, 'EventSink'};
{fistful_deposit_thrift, 'EventSink'};
get_service(source_event_sink) ->
{ff_proto_source_thrift, 'EventSink'};
{fistful_source_thrift, 'EventSink'};
get_service(destination_event_sink) ->
{ff_proto_destination_thrift, 'EventSink'};
{fistful_destination_thrift, 'EventSink'};
get_service(identity_event_sink) ->
{ff_proto_identity_thrift, 'EventSink'};
{fistful_identity_thrift, 'EventSink'};
get_service(wallet_event_sink) ->
{ff_proto_wallet_thrift, 'EventSink'};
{fistful_wallet_thrift, 'EventSink'};
get_service(withdrawal_event_sink) ->
{ff_proto_withdrawal_thrift, 'EventSink'};
{fistful_wthd_thrift, 'EventSink'};
get_service(withdrawal_session_event_sink) ->
{ff_proto_withdrawal_session_thrift, 'EventSink'};
{fistful_wthd_session_thrift, 'EventSink'};
get_service(withdrawal_session_repairer) ->
{ff_proto_withdrawal_session_thrift, 'Repairer'};
{fistful_wthd_session_thrift, 'Repairer'};
get_service(withdrawal_repairer) ->
{ff_proto_withdrawal_thrift, 'Repairer'};
{fistful_wthd_thrift, 'Repairer'};
get_service(deposit_repairer) ->
{ff_proto_deposit_thrift, 'Repairer'};
{fistful_deposit_thrift, 'Repairer'};
get_service(wallet_management) ->
{ff_proto_wallet_thrift, 'Management'};
{fistful_wallet_thrift, 'Management'};
get_service(identity_management) ->
{ff_proto_identity_thrift, 'Management'};
{fistful_identity_thrift, 'Management'};
get_service(destination_management) ->
{ff_proto_destination_thrift, 'Management'};
{fistful_destination_thrift, 'Management'};
get_service(source_management) ->
{ff_proto_source_thrift, 'Management'};
{fistful_source_thrift, 'Management'};
get_service(withdrawal_management) ->
{ff_proto_withdrawal_thrift, 'Management'};
{fistful_wthd_thrift, 'Management'};
get_service(withdrawal_session_management) ->
{ff_proto_withdrawal_session_thrift, 'Management'};
{fistful_wthd_session_thrift, 'Management'};
get_service(deposit_management) ->
{ff_proto_deposit_thrift, 'Management'};
{fistful_deposit_thrift, 'Management'};
get_service(w2w_transfer_event_sink) ->
{ff_proto_w2w_transfer_thrift, 'EventSink'};
{fistful_w2w_transfer_thrift, 'EventSink'};
get_service(w2w_transfer_repairer) ->
{ff_proto_w2w_transfer_thrift, 'Repairer'};
{fistful_w2w_transfer_thrift, 'Repairer'};
get_service(w2w_transfer_management) ->
{ff_proto_w2w_transfer_thrift, 'Management'}.
{fistful_w2w_transfer_thrift, 'Management'}.
-spec get_service_spec(service_name()) -> service_spec().
get_service_spec(Name) ->

View File

@ -2,7 +2,7 @@
-behaviour(ff_codec).
-include_lib("fistful_proto/include/ff_proto_source_thrift.hrl").
-include_lib("fistful_proto/include/fistful_source_thrift.hrl").
-export([unmarshal_source_params/1]).
-export([marshal_source_state/2]).
@ -13,20 +13,20 @@
%% API
-spec unmarshal_source_params(ff_proto_source_thrift:'SourceParams'()) -> ff_source:params().
-spec unmarshal_source_params(fistful_source_thrift:'SourceParams'()) -> ff_source:params().
unmarshal_source_params(Params) ->
genlib_map:compact(#{
id => unmarshal(id, Params#src_SourceParams.id),
identity => unmarshal(id, Params#src_SourceParams.identity_id),
name => unmarshal(string, Params#src_SourceParams.name),
currency => unmarshal(currency_ref, Params#src_SourceParams.currency),
resource => unmarshal(resource, Params#src_SourceParams.resource),
external_id => maybe_unmarshal(id, Params#src_SourceParams.external_id),
metadata => maybe_unmarshal(ctx, Params#src_SourceParams.metadata)
id => unmarshal(id, Params#source_SourceParams.id),
identity => unmarshal(id, Params#source_SourceParams.identity_id),
name => unmarshal(string, Params#source_SourceParams.name),
currency => unmarshal(currency_ref, Params#source_SourceParams.currency),
resource => unmarshal(resource, Params#source_SourceParams.resource),
external_id => maybe_unmarshal(id, Params#source_SourceParams.external_id),
metadata => maybe_unmarshal(ctx, Params#source_SourceParams.metadata)
}).
-spec marshal_source_state(ff_source:source_state(), ff_entity_context:context()) ->
ff_proto_source_thrift:'SourceState'().
fistful_source_thrift:'SourceState'().
marshal_source_state(SourceState, Context) ->
Blocking =
case ff_source:is_accessible(SourceState) of
@ -35,7 +35,7 @@ marshal_source_state(SourceState, Context) ->
_ ->
blocked
end,
#src_SourceState{
#source_SourceState{
id = maybe_marshal(id, ff_source:id(SourceState)),
name = marshal(string, ff_source:name(SourceState)),
resource = marshal(resource, ff_source:resource(SourceState)),
@ -48,9 +48,9 @@ marshal_source_state(SourceState, Context) ->
context = maybe_marshal(ctx, Context)
}.
-spec marshal_event(ff_source_machine:event()) -> ff_proto_source_thrift:'Event'().
-spec marshal_event(ff_source_machine:event()) -> fistful_source_thrift:'Event'().
marshal_event({EventID, {ev, Timestamp, Change}}) ->
#src_Event{
#source_Event{
event_id = ff_codec:marshal(event_id, EventID),
occured_at = ff_codec:marshal(timestamp, Timestamp),
change = marshal(change, Change)
@ -58,7 +58,7 @@ marshal_event({EventID, {ev, Timestamp, Change}}) ->
-spec marshal(ff_codec:type_name(), ff_codec:decoded_value()) -> ff_codec:encoded_value().
marshal(timestamped_change, {ev, Timestamp, Change}) ->
#src_TimestampedChange{
#source_TimestampedChange{
change = marshal(change, Change),
occured_at = ff_codec:marshal(timestamp, Timestamp)
};
@ -67,7 +67,7 @@ marshal(change, {created, Source}) ->
marshal(change, {account, AccountChange}) ->
{account, marshal(account_change, AccountChange)};
marshal(change, {status_changed, Status}) ->
{status, #src_StatusChange{status = marshal(status, Status)}};
{status, #source_StatusChange{status = marshal(status, Status)}};
marshal(
source,
Source = #{
@ -75,7 +75,7 @@ marshal(
resource := Resource
}
) ->
#src_Source{
#source_Source{
id = marshal(id, ff_source:id(Source)),
status = maybe_marshal(status, ff_source:status(Source)),
name = marshal(string, Name),
@ -88,13 +88,13 @@ marshal(resource, #{type := internal} = Internal) ->
{internal, marshal(internal, Internal)};
marshal(internal, Internal) ->
Details = maps:get(details, Internal, undefined),
#src_Internal{
#source_Internal{
details = marshal(string, Details)
};
marshal(status, unauthorized) ->
{unauthorized, #src_Unauthorized{}};
{unauthorized, #source_Unauthorized{}};
marshal(status, authorized) ->
{authorized, #src_Authorized{}};
{authorized, #source_Authorized{}};
marshal(ctx, Ctx) ->
marshal(context, Ctx);
marshal(T, V) ->
@ -103,23 +103,23 @@ marshal(T, V) ->
-spec unmarshal(ff_codec:type_name(), ff_codec:encoded_value()) -> ff_codec:decoded_value().
unmarshal({list, T}, V) ->
[unmarshal(T, E) || E <- V];
unmarshal(repair_scenario, {add_events, #src_AddEventsRepair{events = Events, action = Action}}) ->
unmarshal(repair_scenario, {add_events, #source_AddEventsRepair{events = Events, action = Action}}) ->
{add_events,
genlib_map:compact(#{
events => unmarshal({list, change}, Events),
action => maybe_unmarshal(complex_action, Action)
})};
unmarshal(timestamped_change, TimestampedChange) ->
Timestamp = ff_codec:unmarshal(timestamp, TimestampedChange#src_TimestampedChange.occured_at),
Change = unmarshal(change, TimestampedChange#src_TimestampedChange.change),
Timestamp = ff_codec:unmarshal(timestamp, TimestampedChange#source_TimestampedChange.occured_at),
Change = unmarshal(change, TimestampedChange#source_TimestampedChange.change),
{ev, Timestamp, Change};
unmarshal(change, {created, Source}) ->
{created, unmarshal(source, Source)};
unmarshal(change, {account, AccountChange}) ->
{account, unmarshal(account_change, AccountChange)};
unmarshal(change, {status, #src_StatusChange{status = Status}}) ->
unmarshal(change, {status, #source_StatusChange{status = Status}}) ->
{status_changed, unmarshal(status, Status)};
unmarshal(source, #src_Source{
unmarshal(source, #source_Source{
name = Name,
resource = Resource,
external_id = ExternalID,
@ -134,14 +134,14 @@ unmarshal(source, #src_Source{
created_at => maybe_unmarshal(timestamp_ms, CreatedAt),
metadata => maybe_unmarshal(context, Metadata)
});
unmarshal(resource, {internal, #src_Internal{details = Details}}) ->
unmarshal(resource, {internal, #source_Internal{details = Details}}) ->
genlib_map:compact(#{
type => internal,
details => unmarshal(string, Details)
});
unmarshal(status, {unauthorized, #src_Unauthorized{}}) ->
unmarshal(status, {unauthorized, #source_Unauthorized{}}) ->
unauthorized;
unmarshal(status, {authorized, #src_Authorized{}}) ->
unmarshal(status, {authorized, #source_Authorized{}}) ->
authorized;
unmarshal(ctx, Ctx) ->
maybe_unmarshal(context, Ctx);

View File

@ -4,10 +4,10 @@
-export([publish_events/1]).
-include_lib("fistful_proto/include/ff_proto_source_thrift.hrl").
-include_lib("fistful_proto/include/fistful_source_thrift.hrl").
-type event() :: ff_eventsink_publisher:event(ff_source:event()).
-type sinkevent() :: ff_eventsink_publisher:sinkevent(ff_proto_source_thrift:'SinkEvent'()).
-type sinkevent() :: ff_eventsink_publisher:sinkevent(fistful_source_thrift:'SinkEvent'()).
-spec publish_events(list(event())) -> list(sinkevent()).
publish_events(Events) ->
@ -23,11 +23,11 @@ publish_event(#{
{ev, EventDt, Payload}
}
}) ->
#src_SinkEvent{
#source_SinkEvent{
id = marshal(event_id, ID),
created_at = marshal(timestamp, Dt),
source = marshal(id, SourceID),
payload = #src_EventSinkPayload{
payload = #source_EventSinkPayload{
sequence = marshal(event_id, EventID),
occured_at = marshal(timestamp, EventDt),
changes = [marshal(change, Payload)]

View File

@ -2,7 +2,9 @@
-behaviour(ff_woody_wrapper).
-include_lib("fistful_proto/include/ff_proto_source_thrift.hrl").
-include_lib("fistful_proto/include/fistful_source_thrift.hrl").
-include_lib("fistful_proto/include/fistful_fistful_base_thrift.hrl").
-include_lib("fistful_proto/include/fistful_fistful_thrift.hrl").
%% ff_woody_wrapper callbacks
-export([handle_function/3]).
@ -24,7 +26,7 @@ handle_function(Func, Args, Opts) ->
%% Internals
%%
handle_function_('Create', {Params, Ctx}, Opts) ->
ID = Params#src_SourceParams.id,
ID = Params#source_SourceParams.id,
ok = scoper:add_meta(#{id => ID}),
case
ff_source_machine:create(

View File

@ -3,7 +3,7 @@
%% Storage schema behaviour
-behaviour(machinery_mg_schema).
-include_lib("fistful_proto/include/ff_proto_source_thrift.hrl").
-include_lib("fistful_proto/include/fistful_source_thrift.hrl").
-include_lib("mg_proto/include/mg_proto_state_processing_thrift.hrl").
-export([get_version/1]).
@ -76,13 +76,13 @@ marshal_event(undefined = Version, TimestampedChange, Context) ->
machinery_mg_schema_generic:marshal({event, Version}, TimestampedChange, Context);
marshal_event(1, TimestampedChange, Context) ->
ThriftChange = ff_source_codec:marshal(timestamped_change, TimestampedChange),
Type = {struct, struct, {ff_proto_source_thrift, 'TimestampedChange'}},
Type = {struct, struct, {fistful_source_thrift, 'TimestampedChange'}},
{{bin, ff_proto_utils:serialize(Type, ThriftChange)}, Context}.
-spec unmarshal_event(machinery_mg_schema:version(), machinery_msgpack:t(), context()) -> {event(), context()}.
unmarshal_event(1, EncodedChange, Context) ->
{bin, EncodedThriftChange} = EncodedChange,
Type = {struct, struct, {ff_proto_source_thrift, 'TimestampedChange'}},
Type = {struct, struct, {fistful_source_thrift, 'TimestampedChange'}},
ThriftChange = ff_proto_utils:deserialize(Type, EncodedThriftChange),
{ff_source_codec:unmarshal(timestamped_change, ThriftChange), Context};
unmarshal_event(undefined = Version, EncodedChange, Context0) ->

View File

@ -2,7 +2,7 @@
-behaviour(ff_codec).
-include_lib("fistful_proto/include/ff_proto_w2w_adjustment_thrift.hrl").
-include_lib("fistful_proto/include/fistful_w2w_adj_thrift.hrl").
-export([marshal/2]).
-export([unmarshal/2]).

View File

@ -2,7 +2,9 @@
-behaviour(ff_codec).
-include_lib("fistful_proto/include/ff_proto_w2w_transfer_thrift.hrl").
-include_lib("fistful_proto/include/fistful_w2w_transfer_thrift.hrl").
-include_lib("fistful_proto/include/fistful_w2w_status_thrift.hrl").
-include_lib("fistful_proto/include/fistful_fistful_base_thrift.hrl").
-export([marshal_w2w_transfer_state/2]).
-export([unmarshal_w2w_transfer_params/1]).
@ -13,7 +15,7 @@
%% API
-spec marshal_w2w_transfer_state(w2w_transfer:w2w_transfer_state(), ff_entity_context:context()) ->
ff_proto_w2w_transfer_thrift:'W2WTransferState'().
fistful_w2w_transfer_thrift:'W2WTransferState'().
marshal_w2w_transfer_state(W2WTransferState, Ctx) ->
CashFlow = w2w_transfer:effective_final_cash_flow(W2WTransferState),
Adjustments = w2w_transfer:adjustments(W2WTransferState),
@ -33,7 +35,7 @@ marshal_w2w_transfer_state(W2WTransferState, Ctx) ->
context = marshal(ctx, Ctx)
}.
-spec unmarshal_w2w_transfer_params(ff_proto_w2w_transfer_thrift:'W2WTransferParams'()) ->
-spec unmarshal_w2w_transfer_params(fistful_w2w_transfer_thrift:'W2WTransferParams'()) ->
w2w_transfer_machine:params().
unmarshal_w2w_transfer_params(#w2w_transfer_W2WTransferParams{
id = ID,

View File

@ -4,13 +4,13 @@
-export([publish_events/1]).
-include_lib("fistful_proto/include/ff_proto_w2w_transfer_thrift.hrl").
-include_lib("fistful_proto/include/ff_proto_cashflow_thrift.hrl").
-include_lib("fistful_proto/include/ff_proto_base_thrift.hrl").
-include_lib("fistful_proto/include/fistful_w2w_transfer_thrift.hrl").
-include_lib("fistful_proto/include/fistful_cashflow_thrift.hrl").
-include_lib("fistful_proto/include/fistful_fistful_base_thrift.hrl").
-include_lib("mg_proto/include/mg_proto_state_processing_thrift.hrl").
-type event() :: ff_eventsink_publisher:event(w2w_transfer:event()).
-type sinkevent() :: ff_eventsink_publisher:sinkevent(ff_proto_w2w_transfer_thrift:'SinkEvent'()).
-type sinkevent() :: ff_eventsink_publisher:sinkevent(fistful_w2w_transfer_thrift:'SinkEvent'()).
%%
%% Internals

View File

@ -2,8 +2,9 @@
-behaviour(ff_woody_wrapper).
-include_lib("fistful_proto/include/ff_proto_w2w_transfer_thrift.hrl").
-include_lib("fistful_proto/include/ff_proto_base_thrift.hrl").
-include_lib("fistful_proto/include/fistful_w2w_transfer_thrift.hrl").
-include_lib("fistful_proto/include/fistful_fistful_base_thrift.hrl").
-include_lib("fistful_proto/include/fistful_fistful_thrift.hrl").
%% ff_woody_wrapper callbacks
-export([handle_function/3]).

View File

@ -3,7 +3,7 @@
%% Storage schema behaviour
-behaviour(machinery_mg_schema).
-include_lib("fistful_proto/include/ff_proto_w2w_transfer_thrift.hrl").
-include_lib("fistful_proto/include/fistful_w2w_transfer_thrift.hrl").
-include_lib("mg_proto/include/mg_proto_state_processing_thrift.hrl").
-export([get_version/1]).
@ -73,13 +73,13 @@ unmarshal(T, V, C) when
-spec marshal_event(machinery_mg_schema:version(), event(), context()) -> {machinery_msgpack:t(), context()}.
marshal_event(1, TimestampedChange, Context) ->
ThriftChange = ff_w2w_transfer_codec:marshal(timestamped_change, TimestampedChange),
Type = {struct, struct, {ff_proto_w2w_transfer_thrift, 'TimestampedChange'}},
Type = {struct, struct, {fistful_w2w_transfer_thrift, 'TimestampedChange'}},
{{bin, ff_proto_utils:serialize(Type, ThriftChange)}, Context}.
-spec unmarshal_event(machinery_mg_schema:version(), machinery_msgpack:t(), context()) -> {event(), context()}.
unmarshal_event(1, EncodedChange, Context) ->
{bin, EncodedThriftChange} = EncodedChange,
Type = {struct, struct, {ff_proto_w2w_transfer_thrift, 'TimestampedChange'}},
Type = {struct, struct, {fistful_w2w_transfer_thrift, 'TimestampedChange'}},
ThriftChange = ff_proto_utils:deserialize(Type, EncodedThriftChange),
{ff_w2w_transfer_codec:unmarshal(timestamped_change, ThriftChange), Context}.

View File

@ -4,7 +4,7 @@
-export([handle_function/3]).
-include_lib("fistful_proto/include/ff_proto_fistful_thrift.hrl").
-include_lib("fistful_proto/include/fistful_fistful_thrift.hrl").
-type options() :: undefined.

View File

@ -2,7 +2,7 @@
-behaviour(ff_codec).
-include_lib("fistful_proto/include/ff_proto_w2w_status_thrift.hrl").
-include_lib("fistful_proto/include/fistful_w2w_status_thrift.hrl").
-export([marshal/2]).
-export([unmarshal/2]).

View File

@ -2,7 +2,8 @@
-behaviour(ff_codec).
-include_lib("fistful_proto/include/ff_proto_wallet_thrift.hrl").
-include_lib("fistful_proto/include/fistful_wallet_thrift.hrl").
-include_lib("fistful_proto/include/fistful_account_thrift.hrl").
-export([marshal_wallet_state/3]).
-export([unmarshal_wallet_params/1]).
@ -12,9 +13,9 @@
%% API
-spec marshal_wallet_state(ff_wallet:wallet_state(), ff_wallet:id(), ff_entity_context:context()) ->
ff_proto_wallet_thrift:'WalletState'().
fistful_wallet_thrift:'WalletState'().
marshal_wallet_state(WalletState, ID, Context) ->
#wlt_WalletState{
#wallet_WalletState{
id = marshal(id, ID),
name = marshal(string, ff_wallet:name(WalletState)),
blocking = marshal(blocking, ff_wallet:blocking(WalletState)),
@ -25,8 +26,8 @@ marshal_wallet_state(WalletState, ID, Context) ->
context = marshal(ctx, Context)
}.
-spec unmarshal_wallet_params(ff_proto_wallet_thrift:'WalletParams'()) -> ff_wallet_machine:params().
unmarshal_wallet_params(#wlt_WalletParams{
-spec unmarshal_wallet_params(fistful_wallet_thrift:'WalletParams'()) -> ff_wallet_machine:params().
unmarshal_wallet_params(#wallet_WalletParams{
id = ID,
account_params = AccountParams,
name = Name,
@ -45,7 +46,7 @@ unmarshal_wallet_params(#wlt_WalletParams{
-spec marshal(ff_codec:type_name(), ff_codec:decoded_value()) -> ff_codec:encoded_value().
marshal(timestamped_change, {ev, Timestamp, Change}) ->
#wlt_TimestampedChange{
#wallet_TimestampedChange{
change = marshal(change, Change),
occured_at = ff_codec:marshal(timestamp, Timestamp)
};
@ -54,7 +55,7 @@ marshal(change, {created, Wallet}) ->
marshal(change, {account, AccountChange}) ->
{account, marshal(account_change, AccountChange)};
marshal(wallet, Wallet) ->
#wlt_Wallet{
#wallet_Wallet{
name = marshal(string, maps:get(name, Wallet, <<>>)),
blocking = marshal(blocking, maps:get(blocking, Wallet)),
external_id = maybe_marshal(id, maps:get(external_id, Wallet, undefined)),
@ -78,10 +79,10 @@ marshal(T, V) ->
unmarshal({list, T}, V) ->
[unmarshal(T, E) || E <- V];
unmarshal(timestamped_change, TimestampedChange) ->
Timestamp = ff_codec:unmarshal(timestamp, TimestampedChange#wlt_TimestampedChange.occured_at),
Change = unmarshal(change, TimestampedChange#wlt_TimestampedChange.change),
Timestamp = ff_codec:unmarshal(timestamp, TimestampedChange#wallet_TimestampedChange.occured_at),
Change = unmarshal(change, TimestampedChange#wallet_TimestampedChange.change),
{ev, Timestamp, Change};
unmarshal(repair_scenario, {add_events, #wlt_AddEventsRepair{events = Events, action = Action}}) ->
unmarshal(repair_scenario, {add_events, #wallet_AddEventsRepair{events = Events, action = Action}}) ->
{add_events,
genlib_map:compact(#{
events => unmarshal({list, change}, Events),
@ -91,7 +92,7 @@ unmarshal(change, {created, Wallet}) ->
{created, unmarshal(wallet, Wallet)};
unmarshal(change, {account, AccountChange}) ->
{account, unmarshal(account_change, AccountChange)};
unmarshal(wallet, #wlt_Wallet{
unmarshal(wallet, #wallet_Wallet{
name = Name,
blocking = Blocking,
external_id = ExternalID,

View File

@ -4,10 +4,10 @@
-export([publish_events/1]).
-include_lib("fistful_proto/include/ff_proto_wallet_thrift.hrl").
-include_lib("fistful_proto/include/fistful_wallet_thrift.hrl").
-type event() :: ff_eventsink_publisher:event(ff_wallet:event()).
-type sinkevent() :: ff_eventsink_publisher:sinkevent(ff_proto_wallet_thrift:'SinkEvent'()).
-type sinkevent() :: ff_eventsink_publisher:sinkevent(fistful_wallet_thrift:'SinkEvent'()).
-spec publish_events(list(event())) -> list(sinkevent()).
publish_events(Events) ->
@ -23,11 +23,11 @@ publish_event(#{
{ev, EventDt, Payload}
}
}) ->
#wlt_SinkEvent{
#wallet_SinkEvent{
id = marshal(event_id, ID),
created_at = marshal(timestamp, Dt),
source = marshal(id, SourceID),
payload = #wlt_Event{
payload = #wallet_Event{
sequence = marshal(event_id, EventID),
occured_at = marshal(timestamp, EventDt),
changes = [marshal(change, Payload)]

View File

@ -2,7 +2,9 @@
-behaviour(ff_woody_wrapper).
-include_lib("fistful_proto/include/ff_proto_wallet_thrift.hrl").
-include_lib("fistful_proto/include/fistful_wallet_thrift.hrl").
-include_lib("fistful_proto/include/fistful_fistful_base_thrift.hrl").
-include_lib("fistful_proto/include/fistful_fistful_thrift.hrl").
%% ff_woody_wrapper callbacks
-export([handle_function/3]).
@ -24,7 +26,7 @@ handle_function(Func, Args, Opts) ->
%% Internals
%%
handle_function_('Create', {Params, Context}, Opts) ->
WalletID = Params#wlt_WalletParams.id,
WalletID = Params#wallet_WalletParams.id,
case
ff_wallet_machine:create(
ff_wallet_codec:unmarshal_wallet_params(Params),

View File

@ -3,7 +3,7 @@
%% Storage schema behaviour
-behaviour(machinery_mg_schema).
-include_lib("fistful_proto/include/ff_proto_wallet_thrift.hrl").
-include_lib("fistful_proto/include/fistful_wallet_thrift.hrl").
-include_lib("mg_proto/include/mg_proto_state_processing_thrift.hrl").
-export([get_version/1]).
@ -75,13 +75,13 @@ marshal_event(undefined = Version, TimestampedChange, Context) ->
machinery_mg_schema_generic:marshal({event, Version}, TimestampedChange, Context);
marshal_event(1, TimestampedChange, Context) ->
ThriftChange = ff_wallet_codec:marshal(timestamped_change, TimestampedChange),
Type = {struct, struct, {ff_proto_wallet_thrift, 'TimestampedChange'}},
Type = {struct, struct, {fistful_wallet_thrift, 'TimestampedChange'}},
{{bin, ff_proto_utils:serialize(Type, ThriftChange)}, Context}.
-spec unmarshal_event(machinery_mg_schema:version(), machinery_msgpack:t(), context()) -> {event(), context()}.
unmarshal_event(1, EncodedChange, Context) ->
{bin, EncodedThriftChange} = EncodedChange,
Type = {struct, struct, {ff_proto_wallet_thrift, 'TimestampedChange'}},
Type = {struct, struct, {fistful_wallet_thrift, 'TimestampedChange'}},
ThriftChange = ff_proto_utils:deserialize(Type, EncodedThriftChange),
{ff_wallet_codec:unmarshal(timestamped_change, ThriftChange), Context};
unmarshal_event(undefined = Version, EncodedChange, Context0) ->

View File

@ -2,7 +2,7 @@
-behaviour(ff_woody_wrapper).
-include_lib("damsel/include/dmsl_withdrawals_provider_adapter_thrift.hrl").
-include_lib("damsel/include/dmsl_wthd_provider_thrift.hrl").
%% Exports
@ -10,7 +10,7 @@
%% Types
-type process_callback_result() :: dmsl_withdrawals_provider_adapter_thrift:'ProcessCallbackResult'().
-type process_callback_result() :: dmsl_wthd_provider_thrift:'ProcessCallbackResult'().
%% Handler
@ -30,7 +30,7 @@ handle_function_('ProcessCallback', {Callback}, _Opts) ->
{error, {session_already_finished, Context}} ->
{ok, marshal(process_callback_result, {finished, Context})};
{error, {unknown_session, _Ref}} ->
woody_error:raise(business, #wthadpt_SessionNotFound{})
woody_error:raise(business, #wthd_provider_SessionNotFound{})
end.
%%

View File

@ -2,7 +2,7 @@
-behaviour(ff_codec).
-include_lib("fistful_proto/include/ff_proto_withdrawal_adjustment_thrift.hrl").
-include_lib("fistful_proto/include/fistful_wthd_adj_thrift.hrl").
-export([marshal/2]).
-export([unmarshal/2]).

View File

@ -2,7 +2,11 @@
-behaviour(ff_codec).
-include_lib("fistful_proto/include/ff_proto_withdrawal_thrift.hrl").
-include_lib("fistful_proto/include/fistful_wthd_thrift.hrl").
-include_lib("fistful_proto/include/fistful_wthd_status_thrift.hrl").
-include_lib("fistful_proto/include/fistful_fistful_base_thrift.hrl").
-include_lib("fistful_proto/include/fistful_msgp_thrift.hrl").
-include_lib("fistful_proto/include/fistful_repairer_thrift.hrl").
-export([unmarshal_quote_params/1]).
@ -17,7 +21,7 @@
%% API
-spec unmarshal_quote_params(ff_proto_withdrawal_thrift:'QuoteParams'()) -> ff_withdrawal:quote_params().
-spec unmarshal_quote_params(fistful_wthd_thrift:'QuoteParams'()) -> ff_withdrawal:quote_params().
unmarshal_quote_params(Params) ->
genlib_map:compact(#{
wallet_id => unmarshal(id, Params#wthd_QuoteParams.wallet_id),
@ -28,7 +32,7 @@ unmarshal_quote_params(Params) ->
external_id => maybe_unmarshal(id, Params#wthd_QuoteParams.external_id)
}).
-spec marshal_withdrawal_params(ff_withdrawal:params()) -> ff_proto_withdrawal_thrift:'WithdrawalParams'().
-spec marshal_withdrawal_params(ff_withdrawal:params()) -> fistful_wthd_thrift:'WithdrawalParams'().
marshal_withdrawal_params(Params) ->
#wthd_WithdrawalParams{
id = marshal(id, maps:get(id, Params)),
@ -39,7 +43,7 @@ marshal_withdrawal_params(Params) ->
metadata = maybe_marshal(ctx, maps:get(metadata, Params, undefined))
}.
-spec unmarshal_withdrawal_params(ff_proto_withdrawal_thrift:'WithdrawalParams'()) -> ff_withdrawal:params().
-spec unmarshal_withdrawal_params(fistful_wthd_thrift:'WithdrawalParams'()) -> ff_withdrawal:params().
unmarshal_withdrawal_params(Params) ->
genlib_map:compact(#{
id => unmarshal(id, Params#wthd_WithdrawalParams.id),
@ -52,7 +56,7 @@ unmarshal_withdrawal_params(Params) ->
}).
-spec marshal_withdrawal_state(ff_withdrawal:withdrawal_state(), ff_entity_context:context()) ->
ff_proto_withdrawal_thrift:'WithdrawalState'().
fistful_wthd_thrift:'WithdrawalState'().
marshal_withdrawal_state(WithdrawalState, Context) ->
CashFlow = ff_withdrawal:effective_final_cash_flow(WithdrawalState),
Adjustments = ff_withdrawal:adjustments(WithdrawalState),
@ -77,7 +81,7 @@ marshal_withdrawal_state(WithdrawalState, Context) ->
quote = maybe_marshal(quote_state, ff_withdrawal:quote(WithdrawalState))
}.
-spec marshal_event(ff_withdrawal_machine:event()) -> ff_proto_withdrawal_thrift:'Event'().
-spec marshal_event(ff_withdrawal_machine:event()) -> fistful_wthd_thrift:'Event'().
marshal_event({EventID, {ev, Timestamp, Change}}) ->
#wthd_Event{
event_id = ff_codec:marshal(event_id, EventID),
@ -436,9 +440,9 @@ unmarshal_repair_scenario_test() ->
status = {pending, #wthd_status_Pending{}}
}}
],
action = #ff_repairer_ComplexAction{
action = #repairer_ComplexAction{
timer =
{set_timer, #ff_repairer_SetTimerAction{
{set_timer, #repairer_SetTimerAction{
timer = {timeout, 0}
}}
}

View File

@ -4,13 +4,13 @@
-export([publish_events/1]).
-include_lib("fistful_proto/include/ff_proto_withdrawal_thrift.hrl").
-include_lib("fistful_proto/include/ff_proto_cashflow_thrift.hrl").
-include_lib("fistful_proto/include/ff_proto_base_thrift.hrl").
-include_lib("fistful_proto/include/fistful_wthd_thrift.hrl").
-include_lib("fistful_proto/include/fistful_cashflow_thrift.hrl").
-include_lib("fistful_proto/include/fistful_fistful_base_thrift.hrl").
-include_lib("mg_proto/include/mg_proto_state_processing_thrift.hrl").
-type event() :: ff_eventsink_publisher:event(ff_withdrawal:event()).
-type sinkevent() :: ff_eventsink_publisher:sinkevent(ff_proto_withdrawal_thrift:'SinkEvent'()).
-type sinkevent() :: ff_eventsink_publisher:sinkevent(fistful_wthd_thrift:'SinkEvent'()).
%%
%% Internals

View File

@ -2,7 +2,9 @@
-behaviour(ff_woody_wrapper).
-include_lib("fistful_proto/include/ff_proto_withdrawal_thrift.hrl").
-include_lib("fistful_proto/include/fistful_wthd_thrift.hrl").
-include_lib("fistful_proto/include/fistful_fistful_thrift.hrl").
-include_lib("fistful_proto/include/fistful_fistful_base_thrift.hrl").
%% ff_woody_wrapper callbacks
-export([handle_function/3]).

View File

@ -77,13 +77,13 @@ marshal_event(undefined = Version, TimestampedChange, Context) ->
machinery_mg_schema_generic:marshal({event, Version}, TimestampedChange, Context);
marshal_event(1, TimestampedChange, Context) ->
ThriftChange = ff_withdrawal_codec:marshal(timestamped_change, TimestampedChange),
Type = {struct, struct, {ff_proto_withdrawal_thrift, 'TimestampedChange'}},
Type = {struct, struct, {fistful_wthd_thrift, 'TimestampedChange'}},
{{bin, ff_proto_utils:serialize(Type, ThriftChange)}, Context}.
-spec unmarshal_event(machinery_mg_schema:version(), machinery_msgpack:t(), context()) -> {event(), context()}.
unmarshal_event(1, EncodedChange, Context) ->
{bin, EncodedThriftChange} = EncodedChange,
Type = {struct, struct, {ff_proto_withdrawal_thrift, 'TimestampedChange'}},
Type = {struct, struct, {fistful_wthd_thrift, 'TimestampedChange'}},
ThriftChange = ff_proto_utils:deserialize(Type, EncodedThriftChange),
{ff_withdrawal_codec:unmarshal(timestamped_change, ThriftChange), Context};
unmarshal_event(undefined = Version, EncodedChange, Context) ->

View File

@ -4,7 +4,7 @@
-export([handle_function/3]).
-include_lib("fistful_proto/include/ff_proto_fistful_thrift.hrl").
-include_lib("fistful_proto/include/fistful_fistful_thrift.hrl").
-type options() :: undefined.

View File

@ -2,8 +2,8 @@
-behaviour(ff_codec).
-include_lib("fistful_proto/include/ff_proto_withdrawal_session_thrift.hrl").
-include_lib("fistful_proto/include/ff_proto_base_thrift.hrl").
-include_lib("fistful_proto/include/fistful_wthd_session_thrift.hrl").
-include_lib("fistful_proto/include/fistful_fistful_base_thrift.hrl").
-export([marshal_state/3]).
@ -12,7 +12,7 @@
%% API
-spec marshal_state(ff_withdrawal_session:session_state(), ff_withdrawal_session:id(), ff_entity_context:context()) ->
ff_proto_withdrawal_session_thrift:'SessionState'().
fistful_wthd_session_thrift:'SessionState'().
marshal_state(State, ID, Context) ->
#wthd_session_SessionState{
id = marshal(id, ID),

View File

@ -4,13 +4,13 @@
-export([publish_events/1]).
-include_lib("fistful_proto/include/ff_proto_withdrawal_session_thrift.hrl").
-include_lib("fistful_proto/include/fistful_wthd_session_thrift.hrl").
-include_lib("mg_proto/include/mg_proto_state_processing_thrift.hrl").
-type event() :: ff_eventsink_publisher:event(ff_withdrawal_session:event()).
-type sinkevent() ::
ff_eventsink_publisher:sinkevent(
ff_proto_withdrawal_session_thrift:'SinkEvent'()
fistful_wthd_session_thrift:'SinkEvent'()
).
%%

View File

@ -2,7 +2,8 @@
-behaviour(ff_woody_wrapper).
-include_lib("fistful_proto/include/ff_proto_withdrawal_session_thrift.hrl").
-include_lib("fistful_proto/include/fistful_wthd_session_thrift.hrl").
-include_lib("fistful_proto/include/fistful_fistful_thrift.hrl").
%% ff_woody_wrapper callbacks
-export([handle_function/3]).

View File

@ -3,7 +3,7 @@
%% Storage schema behaviour
-behaviour(machinery_mg_schema).
-include_lib("fistful_proto/include/ff_proto_withdrawal_session_thrift.hrl").
-include_lib("fistful_proto/include/fistful_wthd_session_thrift.hrl").
-include_lib("mg_proto/include/mg_proto_state_processing_thrift.hrl").
-export([get_version/1]).
@ -78,13 +78,13 @@ marshal_event(undefined = Version, TimestampedChange, Context) ->
machinery_mg_schema_generic:marshal({event, Version}, TimestampedChange, Context);
marshal_event(1, TimestampedChange, Context) ->
ThriftChange = ff_withdrawal_session_codec:marshal(timestamped_change, TimestampedChange),
Type = {struct, struct, {ff_proto_withdrawal_session_thrift, 'TimestampedChange'}},
Type = {struct, struct, {fistful_wthd_session_thrift, 'TimestampedChange'}},
{{bin, ff_proto_utils:serialize(Type, ThriftChange)}, Context}.
-spec unmarshal_event(machinery_mg_schema:version(), machinery_msgpack:t(), context()) -> {event(), context()}.
unmarshal_event(1, EncodedChange, Context) ->
{bin, EncodedThriftChange} = EncodedChange,
Type = {struct, struct, {ff_proto_withdrawal_session_thrift, 'TimestampedChange'}},
Type = {struct, struct, {fistful_wthd_session_thrift, 'TimestampedChange'}},
ThriftChange = ff_proto_utils:deserialize(Type, EncodedThriftChange),
{ff_withdrawal_session_codec:unmarshal(timestamped_change, ThriftChange), Context};
unmarshal_event(undefined = Version, EncodedChange, Context0) ->

View File

@ -4,7 +4,7 @@
-export([handle_function/3]).
-include_lib("fistful_proto/include/ff_proto_fistful_thrift.hrl").
-include_lib("fistful_proto/include/fistful_fistful_thrift.hrl").
-type options() :: undefined.

View File

@ -2,7 +2,7 @@
-behaviour(ff_codec).
-include_lib("fistful_proto/include/ff_proto_withdrawal_status_thrift.hrl").
-include_lib("fistful_proto/include/fistful_wthd_status_thrift.hrl").
-export([marshal/2]).
-export([unmarshal/2]).

View File

@ -2,7 +2,15 @@
-include_lib("stdlib/include/assert.hrl").
-include_lib("damsel/include/dmsl_domain_thrift.hrl").
-include_lib("fistful_proto/include/ff_proto_deposit_thrift.hrl").
-include_lib("fistful_proto/include/fistful_cashflow_thrift.hrl").
-include_lib("fistful_proto/include/fistful_deposit_thrift.hrl").
-include_lib("fistful_proto/include/fistful_deposit_revert_thrift.hrl").
-include_lib("fistful_proto/include/fistful_deposit_revert_status_thrift.hrl").
-include_lib("fistful_proto/include/fistful_deposit_revert_adj_thrift.hrl").
-include_lib("fistful_proto/include/fistful_deposit_status_thrift.hrl").
-include_lib("fistful_proto/include/fistful_deposit_adj_thrift.hrl").
-include_lib("fistful_proto/include/fistful_fistful_base_thrift.hrl").
-include_lib("fistful_proto/include/fistful_fistful_thrift.hrl").
%% Common test API
@ -265,34 +273,34 @@ create_adjustment_ok_test(C) ->
} = prepare_standard_environment_with_deposit(C),
AdjustmentID = generate_id(),
ExternalID = generate_id(),
Params = #dep_adj_AdjustmentParams{
Params = #deposit_adj_AdjustmentParams{
id = AdjustmentID,
change =
{change_status, #dep_adj_ChangeStatusRequest{
new_status = {failed, #dep_status_Failed{failure = #'fistful_base_Failure'{code = <<"Ooops">>}}}
{change_status, #deposit_adj_ChangeStatusRequest{
new_status = {failed, #deposit_status_Failed{failure = #'fistful_base_Failure'{code = <<"Ooops">>}}}
}},
external_id = ExternalID
},
{ok, AdjustmentState} = call_deposit('CreateAdjustment', {DepositID, Params}),
ExpectedAdjustment = get_adjustment(DepositID, AdjustmentID),
?assertEqual(AdjustmentID, AdjustmentState#dep_adj_AdjustmentState.id),
?assertEqual(ExternalID, AdjustmentState#dep_adj_AdjustmentState.external_id),
?assertEqual(AdjustmentID, AdjustmentState#deposit_adj_AdjustmentState.id),
?assertEqual(ExternalID, AdjustmentState#deposit_adj_AdjustmentState.external_id),
?assertEqual(
ff_adjustment:created_at(ExpectedAdjustment),
ff_codec:unmarshal(timestamp_ms, AdjustmentState#dep_adj_AdjustmentState.created_at)
ff_codec:unmarshal(timestamp_ms, AdjustmentState#deposit_adj_AdjustmentState.created_at)
),
?assertEqual(
ff_adjustment:domain_revision(ExpectedAdjustment),
AdjustmentState#dep_adj_AdjustmentState.domain_revision
AdjustmentState#deposit_adj_AdjustmentState.domain_revision
),
?assertEqual(
ff_adjustment:party_revision(ExpectedAdjustment),
AdjustmentState#dep_adj_AdjustmentState.party_revision
AdjustmentState#deposit_adj_AdjustmentState.party_revision
),
?assertEqual(
ff_deposit_adjustment_codec:marshal(changes_plan, ff_adjustment:changes_plan(ExpectedAdjustment)),
AdjustmentState#dep_adj_AdjustmentState.changes_plan
AdjustmentState#deposit_adj_AdjustmentState.changes_plan
).
-spec create_adjustment_unavailable_status_error_test(config()) -> test_return().
@ -300,16 +308,16 @@ create_adjustment_unavailable_status_error_test(C) ->
#{
deposit_id := DepositID
} = prepare_standard_environment_with_deposit(C),
Params = #dep_adj_AdjustmentParams{
Params = #deposit_adj_AdjustmentParams{
id = generate_id(),
change =
{change_status, #dep_adj_ChangeStatusRequest{
new_status = {pending, #dep_status_Pending{}}
{change_status, #deposit_adj_ChangeStatusRequest{
new_status = {pending, #deposit_status_Pending{}}
}}
},
Result = call_deposit('CreateAdjustment', {DepositID, Params}),
ExpectedError = #deposit_ForbiddenStatusChange{
target_status = {pending, #dep_status_Pending{}}
target_status = {pending, #deposit_status_Pending{}}
},
?assertEqual({exception, ExpectedError}, Result).
@ -318,16 +326,16 @@ create_adjustment_already_has_status_error_test(C) ->
#{
deposit_id := DepositID
} = prepare_standard_environment_with_deposit(C),
Params = #dep_adj_AdjustmentParams{
Params = #deposit_adj_AdjustmentParams{
id = generate_id(),
change =
{change_status, #dep_adj_ChangeStatusRequest{
new_status = {succeeded, #dep_status_Succeeded{}}
{change_status, #deposit_adj_ChangeStatusRequest{
new_status = {succeeded, #deposit_status_Succeeded{}}
}}
},
Result = call_deposit('CreateAdjustment', {DepositID, Params}),
ExpectedError = #deposit_AlreadyHasStatus{
deposit_status = {succeeded, #dep_status_Succeeded{}}
deposit_status = {succeeded, #deposit_status_Succeeded{}}
},
?assertEqual({exception, ExpectedError}, Result).
@ -438,34 +446,35 @@ create_revert_adjustment_ok_test(C) ->
} = prepare_standard_environment_with_revert(C),
AdjustmentID = generate_id(),
ExternalID = generate_id(),
Params = #dep_rev_adj_AdjustmentParams{
Params = #deposit_revert_adj_AdjustmentParams{
id = AdjustmentID,
change =
{change_status, #dep_rev_adj_ChangeStatusRequest{
new_status = {failed, #dep_rev_status_Failed{failure = #'fistful_base_Failure'{code = <<"Ooops">>}}}
{change_status, #deposit_revert_adj_ChangeStatusRequest{
new_status =
{failed, #deposit_revert_status_Failed{failure = #'fistful_base_Failure'{code = <<"Ooops">>}}}
}},
external_id = ExternalID
},
{ok, AdjustmentState} = call_deposit('CreateRevertAdjustment', {DepositID, RevertID, Params}),
ExpectedAdjustment = get_revert_adjustment(DepositID, RevertID, AdjustmentID),
?assertEqual(AdjustmentID, AdjustmentState#dep_rev_adj_AdjustmentState.id),
?assertEqual(ExternalID, AdjustmentState#dep_rev_adj_AdjustmentState.external_id),
?assertEqual(AdjustmentID, AdjustmentState#deposit_revert_adj_AdjustmentState.id),
?assertEqual(ExternalID, AdjustmentState#deposit_revert_adj_AdjustmentState.external_id),
?assertEqual(
ff_adjustment:created_at(ExpectedAdjustment),
ff_codec:unmarshal(timestamp_ms, AdjustmentState#dep_rev_adj_AdjustmentState.created_at)
ff_codec:unmarshal(timestamp_ms, AdjustmentState#deposit_revert_adj_AdjustmentState.created_at)
),
?assertEqual(
ff_adjustment:domain_revision(ExpectedAdjustment),
AdjustmentState#dep_rev_adj_AdjustmentState.domain_revision
AdjustmentState#deposit_revert_adj_AdjustmentState.domain_revision
),
?assertEqual(
ff_adjustment:party_revision(ExpectedAdjustment),
AdjustmentState#dep_rev_adj_AdjustmentState.party_revision
AdjustmentState#deposit_revert_adj_AdjustmentState.party_revision
),
?assertEqual(
ff_deposit_revert_adjustment_codec:marshal(changes_plan, ff_adjustment:changes_plan(ExpectedAdjustment)),
AdjustmentState#dep_rev_adj_AdjustmentState.changes_plan
AdjustmentState#deposit_revert_adj_AdjustmentState.changes_plan
).
-spec create_revert_adjustment_unavailable_status_error_test(config()) -> test_return().
@ -474,16 +483,16 @@ create_revert_adjustment_unavailable_status_error_test(C) ->
deposit_id := DepositID,
revert_id := RevertID
} = prepare_standard_environment_with_revert(C),
Params = #dep_rev_adj_AdjustmentParams{
Params = #deposit_revert_adj_AdjustmentParams{
id = generate_id(),
change =
{change_status, #dep_rev_adj_ChangeStatusRequest{
new_status = {pending, #dep_rev_status_Pending{}}
{change_status, #deposit_revert_adj_ChangeStatusRequest{
new_status = {pending, #deposit_revert_status_Pending{}}
}}
},
Result = call_deposit('CreateRevertAdjustment', {DepositID, RevertID, Params}),
ExpectedError = #deposit_ForbiddenRevertStatusChange{
target_status = {pending, #dep_rev_status_Pending{}}
target_status = {pending, #deposit_revert_status_Pending{}}
},
?assertEqual({exception, ExpectedError}, Result).
@ -493,16 +502,16 @@ create_revert_adjustment_already_has_status_error_test(C) ->
deposit_id := DepositID,
revert_id := RevertID
} = prepare_standard_environment_with_revert(C),
Params = #dep_rev_adj_AdjustmentParams{
Params = #deposit_revert_adj_AdjustmentParams{
id = generate_id(),
change =
{change_status, #dep_rev_adj_ChangeStatusRequest{
new_status = {succeeded, #dep_rev_status_Succeeded{}}
{change_status, #deposit_revert_adj_ChangeStatusRequest{
new_status = {succeeded, #deposit_revert_status_Succeeded{}}
}}
},
Result = call_deposit('CreateRevertAdjustment', {DepositID, RevertID, Params}),
ExpectedError = #deposit_RevertAlreadyHasStatus{
revert_status = {succeeded, #dep_rev_status_Succeeded{}}
revert_status = {succeeded, #deposit_revert_status_Succeeded{}}
},
?assertEqual({exception, ExpectedError}, Result).
@ -512,19 +521,20 @@ deposit_state_content_test(C) ->
deposit_id := DepositID,
revert_id := RevertID
} = prepare_standard_environment_with_revert(C),
AdjustmentParams = #dep_adj_AdjustmentParams{
AdjustmentParams = #deposit_adj_AdjustmentParams{
id = generate_id(),
change =
{change_status, #dep_adj_ChangeStatusRequest{
new_status = {failed, #dep_status_Failed{failure = #'fistful_base_Failure'{code = <<"Ooops">>}}}
{change_status, #deposit_adj_ChangeStatusRequest{
new_status = {failed, #deposit_status_Failed{failure = #'fistful_base_Failure'{code = <<"Ooops">>}}}
}}
},
{ok, _} = call_deposit('CreateAdjustment', {DepositID, AdjustmentParams}),
RevertAdjustmentParams = #dep_rev_adj_AdjustmentParams{
RevertAdjustmentParams = #deposit_revert_adj_AdjustmentParams{
id = generate_id(),
change =
{change_status, #dep_rev_adj_ChangeStatusRequest{
new_status = {failed, #dep_rev_status_Failed{failure = #'fistful_base_Failure'{code = <<"Ooops">>}}}
{change_status, #deposit_revert_adj_ChangeStatusRequest{
new_status =
{failed, #deposit_revert_status_Failed{failure = #'fistful_base_Failure'{code = <<"Ooops">>}}}
}}
},
{ok, _} = call_deposit('CreateRevertAdjustment', {DepositID, RevertID, RevertAdjustmentParams}),

View File

@ -1,6 +1,9 @@
-module(ff_destination_handler_SUITE).
-include_lib("fistful_proto/include/ff_proto_destination_thrift.hrl").
-include_lib("fistful_proto/include/fistful_destination_thrift.hrl").
-include_lib("fistful_proto/include/fistful_fistful_base_thrift.hrl").
-include_lib("fistful_proto/include/fistful_account_thrift.hrl").
-include_lib("fistful_proto/include/fistful_fistful_thrift.hrl").
-export([all/0]).
-export([groups/0]).
@ -148,7 +151,7 @@ create_destination_forbidden_withdrawal_method_fail(C) ->
IdentityID = create_identity(Party, C),
Ctx = ff_entity_context_codec:marshal(#{<<"NS">> => #{}}),
Metadata = ff_entity_context_codec:marshal(#{<<"metadata">> => #{<<"some key">> => <<"some data">>}}),
Params = #dst_DestinationParams{
Params = #destination_DestinationParams{
id = ID,
identity = IdentityID,
name = DstName,
@ -172,7 +175,7 @@ create_destination_ok(Resource, C) ->
IdentityID = create_identity(Party, C),
Ctx = ff_entity_context_codec:marshal(#{<<"NS">> => #{}}),
Metadata = ff_entity_context_codec:marshal(#{<<"metadata">> => #{<<"some key">> => <<"some data">>}}),
Params = #dst_DestinationParams{
Params = #destination_DestinationParams{
id = ID,
identity = IdentityID,
name = DstName,
@ -182,31 +185,31 @@ create_destination_ok(Resource, C) ->
metadata = Metadata
},
{ok, Dst} = call_service('Create', {Params, Ctx}),
DstName = Dst#dst_DestinationState.name,
ID = Dst#dst_DestinationState.id,
Resource = Dst#dst_DestinationState.resource,
ExternalId = Dst#dst_DestinationState.external_id,
Metadata = Dst#dst_DestinationState.metadata,
Ctx = Dst#dst_DestinationState.context,
DstName = Dst#destination_DestinationState.name,
ID = Dst#destination_DestinationState.id,
Resource = Dst#destination_DestinationState.resource,
ExternalId = Dst#destination_DestinationState.external_id,
Metadata = Dst#destination_DestinationState.metadata,
Ctx = Dst#destination_DestinationState.context,
Account = Dst#dst_DestinationState.account,
Account = Dst#destination_DestinationState.account,
IdentityID = Account#account_Account.identity,
#'fistful_base_CurrencyRef'{symbolic_code = Currency} = Account#account_Account.currency,
{authorized, #dst_Authorized{}} = ct_helper:await(
{authorized, #dst_Authorized{}},
{authorized, #destination_Authorized{}} = ct_helper:await(
{authorized, #destination_Authorized{}},
fun() ->
{ok, #dst_DestinationState{status = Status}} =
{ok, #destination_DestinationState{status = Status}} =
call_service('Get', {ID, #'fistful_base_EventRange'{}}),
Status
end,
genlib_retry:linear(15, 1000)
),
{ok, #dst_DestinationState{}} = call_service('Get', {ID, #'fistful_base_EventRange'{}}).
{ok, #destination_DestinationState{}} = call_service('Get', {ID, #'fistful_base_EventRange'{}}).
call_service(Fun, Args) ->
Service = {ff_proto_destination_thrift, 'Management'},
Service = {fistful_destination_thrift, 'Management'},
Request = {Service, Fun, Args},
Client = ff_woody_client:new(#{
url => <<"http://localhost:8022/v1/destination">>,

View File

@ -1,6 +1,8 @@
-module(ff_eventsink_SUITE).
-include_lib("fistful_proto/include/ff_proto_withdrawal_thrift.hrl").
-include_lib("fistful_proto/include/fistful_wthd_thrift.hrl").
-include_lib("fistful_proto/include/fistful_evsink_thrift.hrl").
-include_lib("fistful_proto/include/fistful_transfer_thrift.hrl").
-export([all/0]).
-export([groups/0]).

View File

@ -1,7 +1,9 @@
-module(ff_identity_handler_SUITE).
-include_lib("stdlib/include/assert.hrl").
-include_lib("fistful_proto/include/ff_proto_identity_thrift.hrl").
-include_lib("fistful_proto/include/fistful_identity_thrift.hrl").
-include_lib("fistful_proto/include/fistful_fistful_base_thrift.hrl").
-include_lib("fistful_proto/include/fistful_fistful_thrift.hrl").
-export([all/0]).
-export([init_per_suite/1]).
@ -70,19 +72,19 @@ create_identity_ok(_C) ->
Ctx = #{<<"NS">> => #{<<"owner">> => PartyID}},
Metadata = ff_entity_context_codec:marshal(#{<<"metadata">> => #{<<"some key">> => <<"some data">>}}),
Identity0 = create_identity(EID, Name, PartyID, ProvID, Ctx, Metadata),
IID = Identity0#idnt_IdentityState.id,
IID = Identity0#identity_IdentityState.id,
{ok, Identity1} = call_api('Get', {IID, #'fistful_base_EventRange'{}}),
ProvID = Identity1#idnt_IdentityState.provider_id,
IID = Identity1#idnt_IdentityState.id,
Name = Identity1#idnt_IdentityState.name,
PartyID = Identity1#idnt_IdentityState.party_id,
unblocked = Identity1#idnt_IdentityState.blocking,
Metadata = Identity1#idnt_IdentityState.metadata,
ProvID = Identity1#identity_IdentityState.provider_id,
IID = Identity1#identity_IdentityState.id,
Name = Identity1#identity_IdentityState.name,
PartyID = Identity1#identity_IdentityState.party_id,
unblocked = Identity1#identity_IdentityState.blocking,
Metadata = Identity1#identity_IdentityState.metadata,
Ctx0 = Ctx#{
<<"com.rbkmoney.wapi">> => #{<<"name">> => Name}
},
Ctx0 = ff_entity_context_codec:unmarshal(Identity1#idnt_IdentityState.context),
Ctx0 = ff_entity_context_codec:unmarshal(Identity1#identity_IdentityState.context),
ok.
get_event_unknown_identity_ok(_C) ->
@ -106,7 +108,7 @@ get_withdrawal_methods_ok(_C) ->
Name = <<"Identity Name">>,
ProvID = <<"good-one">>,
Metadata = ff_entity_context_codec:marshal(#{<<"metadata">> => #{<<"some key">> => <<"some data">>}}),
#idnt_IdentityState{id = ID} = create_identity(EID, Name, PID, ProvID, Ctx, Metadata),
#identity_IdentityState{id = ID} = create_identity(EID, Name, PID, ProvID, Ctx, Metadata),
{ok, [
{bank_card, _},
{crypto_currency, _},
@ -121,7 +123,7 @@ get_withdrawal_methods_ok(_C) ->
%%----------
create_identity(EID, Name, PartyID, ProvID, Ctx, Metadata) ->
Params = #idnt_IdentityParams{
Params = #identity_IdentityParams{
id = genlib:unique(),
name = Name,
party = PartyID,
@ -136,7 +138,7 @@ create_identity(EID, Name, PartyID, ProvID, Ctx, Metadata) ->
IdentityState.
call_api(Fun, Args) ->
Service = {ff_proto_identity_thrift, 'Management'},
Service = {fistful_identity_thrift, 'Management'},
Request = {Service, Fun, Args},
Client = ff_woody_client:new(#{
url => <<"http://localhost:8022/v1/identity">>,

View File

@ -1,7 +1,8 @@
-module(ff_provider_handler_SUITE).
-include_lib("stdlib/include/assert.hrl").
-include_lib("fistful_proto/include/ff_proto_provider_thrift.hrl").
-include_lib("fistful_proto/include/fistful_provider_thrift.hrl").
-include_lib("fistful_proto/include/fistful_fistful_thrift.hrl").
-export([all/0]).
-export([groups/0]).

View File

@ -1,7 +1,10 @@
-module(ff_source_handler_SUITE).
-include_lib("stdlib/include/assert.hrl").
-include_lib("fistful_proto/include/ff_proto_source_thrift.hrl").
-include_lib("fistful_proto/include/fistful_source_thrift.hrl").
-include_lib("fistful_proto/include/fistful_account_thrift.hrl").
-include_lib("fistful_proto/include/fistful_fistful_base_thrift.hrl").
-include_lib("fistful_proto/include/fistful_fistful_thrift.hrl").
-export([all/0]).
-export([groups/0]).
@ -76,27 +79,27 @@ end_per_testcase(_Name, _C) ->
-spec get_source_events_ok_test(config()) -> test_return().
get_source_events_ok_test(C) ->
Resource =
{internal, #src_Internal{
{internal, #source_Internal{
details = <<"details">>
}},
State = create_source_ok(Resource, C),
ID = State#src_SourceState.id,
ID = State#source_SourceState.id,
{ok, [_Event | _Rest]} = call_service('GetEvents', {ID, #'fistful_base_EventRange'{}}).
-spec get_source_context_ok_test(config()) -> test_return().
get_source_context_ok_test(C) ->
Resource =
{internal, #src_Internal{
{internal, #source_Internal{
details = <<"details">>
}},
State = create_source_ok(Resource, C),
ID = State#src_SourceState.id,
ID = State#source_SourceState.id,
{ok, _Context} = call_service('GetContext', {ID}).
-spec create_source_ok_test(config()) -> test_return().
create_source_ok_test(C) ->
Resource =
{internal, #src_Internal{
{internal, #source_Internal{
details = <<"details">>
}},
create_source_ok(Resource, C).
@ -121,7 +124,7 @@ create_source_ok(Resource, C) ->
IdentityID = create_identity(Party, C),
Ctx = ff_entity_context_codec:marshal(#{<<"NS">> => #{}}),
Metadata = ff_entity_context_codec:marshal(#{<<"metadata">> => #{<<"some key">> => <<"some data">>}}),
Params = #src_SourceParams{
Params = #source_SourceParams{
id = ID,
identity_id = IdentityID,
name = Name,
@ -131,34 +134,34 @@ create_source_ok(Resource, C) ->
metadata = Metadata
},
{ok, Src} = call_service('Create', {Params, Ctx}),
Name = Src#src_SourceState.name,
ID = Src#src_SourceState.id,
Resource = Src#src_SourceState.resource,
ExternalId = Src#src_SourceState.external_id,
Metadata = Src#src_SourceState.metadata,
Ctx = Src#src_SourceState.context,
Name = Src#source_SourceState.name,
ID = Src#source_SourceState.id,
Resource = Src#source_SourceState.resource,
ExternalId = Src#source_SourceState.external_id,
Metadata = Src#source_SourceState.metadata,
Ctx = Src#source_SourceState.context,
Account = Src#src_SourceState.account,
Account = Src#source_SourceState.account,
IdentityID = Account#account_Account.identity,
#'fistful_base_CurrencyRef'{symbolic_code = Currency} = Account#account_Account.currency,
{unauthorized, #src_Unauthorized{}} = Src#src_SourceState.status,
{unauthorized, #source_Unauthorized{}} = Src#source_SourceState.status,
{authorized, #src_Authorized{}} = ct_helper:await(
{authorized, #src_Authorized{}},
{authorized, #source_Authorized{}} = ct_helper:await(
{authorized, #source_Authorized{}},
fun() ->
{ok, #src_SourceState{status = Status}} =
{ok, #source_SourceState{status = Status}} =
call_service('Get', {ID, #'fistful_base_EventRange'{}}),
Status
end,
genlib_retry:linear(15, 1000)
),
{ok, #src_SourceState{} = State} = call_service('Get', {ID, #'fistful_base_EventRange'{}}),
{ok, #source_SourceState{} = State} = call_service('Get', {ID, #'fistful_base_EventRange'{}}),
State.
call_service(Fun, Args) ->
Service = {ff_proto_source_thrift, 'Management'},
Service = {fistful_source_thrift, 'Management'},
Request = {Service, Fun, Args},
Client = ff_woody_client:new(#{
url => <<"http://localhost:8022/v1/source">>,

View File

@ -1,7 +1,11 @@
-module(ff_w2w_transfer_handler_SUITE).
-include_lib("stdlib/include/assert.hrl").
-include_lib("fistful_proto/include/ff_proto_w2w_transfer_thrift.hrl").
-include_lib("fistful_proto/include/fistful_w2w_transfer_thrift.hrl").
-include_lib("fistful_proto/include/fistful_w2w_adj_thrift.hrl").
-include_lib("fistful_proto/include/fistful_w2w_status_thrift.hrl").
-include_lib("fistful_proto/include/fistful_fistful_base_thrift.hrl").
-include_lib("fistful_proto/include/fistful_fistful_thrift.hrl").
-export([all/0]).
-export([groups/0]).

View File

@ -1,8 +1,10 @@
-module(ff_wallet_handler_SUITE).
-include_lib("stdlib/include/assert.hrl").
-include_lib("fistful_proto/include/ff_proto_wallet_thrift.hrl").
-include_lib("damsel/include/dmsl_payment_processing_thrift.hrl").
-include_lib("fistful_proto/include/fistful_wallet_thrift.hrl").
-include_lib("fistful_proto/include/fistful_fistful_thrift.hrl").
-include_lib("fistful_proto/include/fistful_fistful_base_thrift.hrl").
-include_lib("fistful_proto/include/fistful_account_thrift.hrl").
-export([all/0]).
-export([groups/0]).
@ -97,14 +99,14 @@ create_ok(C) ->
CreateResult = call_service('Create', {Params, Ctx}),
GetResult = call_service('Get', {ID, #'fistful_base_EventRange'{}}),
{ok, Wallet} = GetResult,
Account = Wallet#wlt_WalletState.account,
Account = Wallet#wallet_WalletState.account,
CurrencyRef = Account#account_Account.currency,
?assertMatch(CreateResult, GetResult),
?assertMatch(<<"Valet">>, Wallet#wlt_WalletState.name),
?assertMatch(unblocked, Wallet#wlt_WalletState.blocking),
?assertMatch(ExternalID, Wallet#wlt_WalletState.external_id),
?assertMatch(Metadata, Wallet#wlt_WalletState.metadata),
?assertMatch(Ctx, Wallet#wlt_WalletState.context),
?assertMatch(<<"Valet">>, Wallet#wallet_WalletState.name),
?assertMatch(unblocked, Wallet#wallet_WalletState.blocking),
?assertMatch(ExternalID, Wallet#wallet_WalletState.external_id),
?assertMatch(Metadata, Wallet#wallet_WalletState.metadata),
?assertMatch(Ctx, Wallet#wallet_WalletState.context),
?assertMatch(IdentityID, Account#account_Account.identity),
?assertMatch(Currency, CurrencyRef#'fistful_base_CurrencyRef'.symbolic_code).
@ -156,10 +158,10 @@ get_account_balance(C) ->
Metadata = ff_entity_context_codec:marshal(#{<<"metadata">> => #{<<"some key">> => <<"some data">>}}),
Params = construct_wallet_params(ID, IdentityID, Currency, ExternalID, Metadata),
{ok, Wallet} = call_service('Create', {Params, Ctx}),
WalletID = Wallet#wlt_WalletState.id,
WalletID = Wallet#wallet_WalletState.id,
{ok, AccountBalance} = call_service('GetAccountBalance', {WalletID}),
CurrencyRef = AccountBalance#account_AccountBalance.currency,
Account = Wallet#wlt_WalletState.account,
Account = Wallet#wallet_WalletState.account,
AccountID = Account#account_Account.id,
?assertMatch(AccountID, AccountBalance#account_AccountBalance.id),
?assertMatch(Currency, CurrencyRef#'fistful_base_CurrencyRef'.symbolic_code),
@ -171,7 +173,7 @@ get_account_balance(C) ->
%% Internal
%%-----------
call_service(Fun, Args) ->
Service = {ff_proto_wallet_thrift, 'Management'},
Service = {fistful_wallet_thrift, 'Management'},
Request = {Service, Fun, Args},
Client = ff_woody_client:new(#{
url => <<"http://localhost:8022/v1/wallet">>,
@ -199,21 +201,21 @@ create_identity(Party, Name, ProviderID, _C) ->
ID.
suspend_party(Party, C) ->
Service = {dmsl_payment_processing_thrift, 'PartyManagement'},
Service = {dmsl_payproc_thrift, 'PartyManagement'},
Args = {Party},
Request = {Service, 'Suspend', Args},
_ = ff_woody_client:call(partymgmt, Request, ct_helper:get_woody_ctx(C)),
ok.
block_party(Party, C) ->
Service = {dmsl_payment_processing_thrift, 'PartyManagement'},
Service = {dmsl_payproc_thrift, 'PartyManagement'},
Args = {Party, <<"BECAUSE">>},
Request = {Service, 'Block', Args},
_ = ff_woody_client:call(partymgmt, Request, ct_helper:get_woody_ctx(C)),
ok.
construct_wallet_params(ID, IdentityID, Currency) ->
#wlt_WalletParams{
#wallet_WalletParams{
id = ID,
name = <<"Valet">>,
account_params = #account_AccountParams{
@ -223,7 +225,7 @@ construct_wallet_params(ID, IdentityID, Currency) ->
}.
construct_wallet_params(ID, IdentityID, Currency, ExternalID) ->
#wlt_WalletParams{
#wallet_WalletParams{
id = ID,
name = <<"Valet">>,
external_id = ExternalID,
@ -234,7 +236,7 @@ construct_wallet_params(ID, IdentityID, Currency, ExternalID) ->
}.
construct_wallet_params(ID, IdentityID, Currency, ExternalID, Metadata) ->
#wlt_WalletParams{
#wallet_WalletParams{
id = ID,
name = <<"Valet">>,
external_id = ExternalID,

View File

@ -2,7 +2,12 @@
-include_lib("stdlib/include/assert.hrl").
-include_lib("damsel/include/dmsl_domain_thrift.hrl").
-include_lib("fistful_proto/include/ff_proto_withdrawal_thrift.hrl").
-include_lib("fistful_proto/include/fistful_wthd_thrift.hrl").
-include_lib("fistful_proto/include/fistful_wthd_adj_thrift.hrl").
-include_lib("fistful_proto/include/fistful_wthd_status_thrift.hrl").
-include_lib("fistful_proto/include/fistful_fistful_thrift.hrl").
-include_lib("fistful_proto/include/fistful_fistful_base_thrift.hrl").
-include_lib("fistful_proto/include/fistful_cashflow_thrift.hrl").
-export([all/0]).
-export([groups/0]).

View File

@ -1,8 +1,9 @@
-module(ff_withdrawal_session_repair_SUITE).
-include_lib("stdlib/include/assert.hrl").
-include_lib("fistful_proto/include/ff_proto_withdrawal_session_thrift.hrl").
-include_lib("fistful_proto/include/fistful_wthd_session_thrift.hrl").
-include_lib("damsel/include/dmsl_domain_thrift.hrl").
-include_lib("fistful_proto/include/fistful_fistful_base_thrift.hrl").
-export([all/0]).
-export([groups/0]).
@ -178,7 +179,8 @@ create_failed_session(IdentityID, DestinationID, _C) ->
resource => DestinationResource,
route => #{
version => 1,
provider_id => 1
provider_id => 1,
terminal_id => 1
}
},
ok = ff_withdrawal_session_machine:create(ID, TransferData, SessionParams),
@ -191,7 +193,7 @@ get_session_status(ID) ->
ff_withdrawal_session:status(Session).
call_repair(Args) ->
Service = {ff_proto_withdrawal_session_thrift, 'Repairer'},
Service = {fistful_wthd_session_thrift, 'Repairer'},
Request = {Service, 'Repair', Args},
Client = ff_woody_client:new(#{
url => <<"http://localhost:8022/v1/repair/withdrawal/session">>,

View File

@ -1,7 +1,7 @@
%%% Client for adapter for withdrawal provider
-module(ff_adapter_withdrawal).
-include_lib("damsel/include/dmsl_withdrawals_provider_adapter_thrift.hrl").
-include_lib("damsel/include/dmsl_wthd_provider_thrift.hrl").
%% Accessors
@ -172,18 +172,18 @@ get_quote(Adapter, Params, AOpt) ->
%%
call(Adapter, Function, Args) ->
Request = {{dmsl_withdrawals_provider_adapter_thrift, 'Adapter'}, Function, Args},
Request = {{dmsl_wthd_provider_thrift, 'Adapter'}, Function, Args},
ff_woody_client:call(Adapter, Request).
-spec decode_result
(dmsl_withdrawals_provider_adapter_thrift:'ProcessResult'()) -> {ok, process_result()};
(dmsl_withdrawals_provider_adapter_thrift:'Quote'()) -> {ok, quote()};
(dmsl_withdrawals_provider_adapter_thrift:'CallbackResult'()) -> {ok, handle_callback_result()}.
decode_result(#wthadpt_ProcessResult{} = ProcessResult) ->
(dmsl_wthd_provider_thrift:'ProcessResult'()) -> {ok, process_result()};
(dmsl_wthd_provider_thrift:'Quote'()) -> {ok, quote()};
(dmsl_wthd_provider_thrift:'CallbackResult'()) -> {ok, handle_callback_result()}.
decode_result(#wthd_provider_ProcessResult{} = ProcessResult) ->
{ok, unmarshal(process_result, ProcessResult)};
decode_result(#wthadpt_Quote{} = Quote) ->
decode_result(#wthd_provider_Quote{} = Quote) ->
{ok, unmarshal(quote, Quote)};
decode_result(#wthadpt_CallbackResult{} = CallbackResult) ->
decode_result(#wthd_provider_CallbackResult{} = CallbackResult) ->
{ok, unmarshal(callback_result, CallbackResult)}.
%% @doc
@ -199,19 +199,19 @@ decode_result(#wthadpt_CallbackResult{} = CallbackResult) ->
%%
%% @todo Remove this code when adapter stops set TransactionInfo to field Success.trx_info
rebind_transaction_info(#wthadpt_ProcessResult{intent = Intent} = Result) ->
{NewIntent, TransactionInfo} = extract_transaction_info(Intent, Result#wthadpt_ProcessResult.trx),
Result#wthadpt_ProcessResult{intent = NewIntent, trx = TransactionInfo};
rebind_transaction_info(#wthadpt_CallbackResult{intent = Intent} = Result) ->
{NewIntent, TransactionInfo} = extract_transaction_info(Intent, Result#wthadpt_CallbackResult.trx),
Result#wthadpt_CallbackResult{intent = NewIntent, trx = TransactionInfo}.
rebind_transaction_info(#wthd_provider_ProcessResult{intent = Intent} = Result) ->
{NewIntent, TransactionInfo} = extract_transaction_info(Intent, Result#wthd_provider_ProcessResult.trx),
Result#wthd_provider_ProcessResult{intent = NewIntent, trx = TransactionInfo};
rebind_transaction_info(#wthd_provider_CallbackResult{intent = Intent} = Result) ->
{NewIntent, TransactionInfo} = extract_transaction_info(Intent, Result#wthd_provider_CallbackResult.trx),
Result#wthd_provider_CallbackResult{intent = NewIntent, trx = TransactionInfo}.
extract_transaction_info({finish, #wthadpt_FinishIntent{status = {success, Success}}}, TransactionInfo) ->
extract_transaction_info({finish, #wthd_provider_FinishIntent{status = {success, Success}}}, TransactionInfo) ->
{
{finish, #wthadpt_FinishIntent{status = {success, #wthadpt_Success{trx_info = undefined}}}},
{finish, #wthd_provider_FinishIntent{status = {success, #wthd_provider_Success{trx_info = undefined}}}},
case Success of
#wthadpt_Success{trx_info = undefined} -> TransactionInfo;
#wthadpt_Success{trx_info = LegacyTransactionInfo} -> LegacyTransactionInfo
#wthd_provider_Success{trx_info = undefined} -> TransactionInfo;
#wthd_provider_Success{trx_info = LegacyTransactionInfo} -> LegacyTransactionInfo
end
};
extract_transaction_info(Intent, TransactionInfo) ->

View File

@ -1,7 +1,10 @@
-module(ff_adapter_withdrawal_codec).
-include_lib("damsel/include/dmsl_withdrawals_provider_adapter_thrift.hrl").
-include_lib("damsel/include/dmsl_wthd_domain_thrift.hrl").
-include_lib("damsel/include/dmsl_wthd_provider_thrift.hrl").
-include_lib("damsel/include/dmsl_domain_thrift.hrl").
-include_lib("damsel/include/dmsl_base_thrift.hrl").
-include_lib("damsel/include/dmsl_msgpack_thrift.hrl").
-export([marshal/2]).
-export([unmarshal/2]).
@ -32,12 +35,12 @@ marshal(adapter_state, ASt) ->
marshal(body, {Amount, CurrencyID}) ->
{ok, Currency} = ff_currency:get(CurrencyID),
DomainCurrency = marshal(currency, Currency),
#wthadpt_Cash{amount = Amount, currency = DomainCurrency};
#wthd_provider_Cash{amount = Amount, currency = DomainCurrency};
marshal(callback, #{
tag := Tag,
payload := Payload
}) ->
#wthadpt_Callback{
#wthd_provider_Callback{
tag = Tag,
payload = Payload
};
@ -50,14 +53,14 @@ marshal(
) ->
NextState = genlib_map:get(next_state, Params),
TransactionInfo = genlib_map:get(transaction_info, Params),
#wthadpt_CallbackResult{
#wthd_provider_CallbackResult{
intent = marshal(intent, Intent),
response = marshal(callback_response, Response),
next_state = maybe_marshal(adapter_state, NextState),
trx = maybe_marshal(transaction_info, TransactionInfo)
};
marshal(callback_response, #{payload := Payload}) ->
#wthadpt_CallbackResponse{payload = Payload};
#wthd_provider_CallbackResponse{payload = Payload};
marshal(currency, #{
name := Name,
symcode := Symcode,
@ -87,8 +90,9 @@ marshal(payment_service, #{id := Ref}) when is_binary(Ref) ->
};
marshal(identity, Identity) ->
% TODO: Add real contact fields
#wthdm_Identity{
#wthd_domain_Identity{
id = maps:get(id, Identity),
owner_id = maps:get(owner_id, Identity, undefined),
documents = marshal(identity_documents, Identity),
contact = [{phone_number, <<"9876543210">>}]
};
@ -100,27 +104,27 @@ marshal(identity_documents, Identity) ->
marshal(challenge_documents, Challenge)
end;
marshal(intent, {finish, success}) ->
{finish, #wthadpt_FinishIntent{
status = {success, #wthadpt_Success{}}
{finish, #wthd_provider_FinishIntent{
status = {success, #wthd_provider_Success{}}
}};
marshal(intent, {finish, {success, TrxInfo}}) ->
{finish, #wthadpt_FinishIntent{
{finish, #wthd_provider_FinishIntent{
status =
{success, #wthadpt_Success{
{success, #wthd_provider_Success{
trx_info = marshal(transaction_info, TrxInfo)
}}
}};
marshal(intent, {finish, {failed, Failure}}) ->
{finish, #wthadpt_FinishIntent{
{finish, #wthd_provider_FinishIntent{
status = {failure, ff_dmsl_codec:marshal(failure, Failure)}
}};
marshal(intent, {sleep, V = #{timer := Timer}}) ->
{sleep, #wthadpt_SleepIntent{
{sleep, #wthd_provider_SleepIntent{
timer = ff_codec:marshal(timer, Timer),
callback_tag = maps:get(tag, V, undefined)
}};
marshal(process_callback_result, {succeeded, CallbackResponse}) ->
{succeeded, #wthadpt_ProcessCallbackSucceeded{
{succeeded, #wthd_provider_ProcessCallbackSucceeded{
response = marshal(callback_response, CallbackResponse)
}};
marshal(
@ -131,7 +135,7 @@ marshal(
opts := Options
}}
) ->
{finished, #wthadpt_ProcessCallbackFinished{
{finished, #wthd_provider_ProcessCallbackFinished{
withdrawal = marshal(withdrawal, Withdrawal),
state = marshal(adapter_state, AdapterState),
opts = Options
@ -147,7 +151,7 @@ marshal(
ExternalID = maps:get(external_id, Params, undefined),
{ok, CurrencyFrom} = ff_currency:get(CurrencyIDFrom),
{ok, CurrencyTo} = ff_currency:get(CurrencyIDTo),
#wthadpt_GetQuoteParams{
#wthd_provider_GetQuoteParams{
idempotency_id = ExternalID,
currency_from = marshal(currency, CurrencyFrom),
currency_to = marshal(currency, CurrencyTo),
@ -160,7 +164,7 @@ marshal(quote, #{
expires_on := ExpiresOn,
quote_data := QuoteData
}) ->
#wthadpt_Quote{
#wthd_provider_Quote{
cash_from = marshal(body, CashFrom),
cash_to = marshal(body, CashTo),
created_at = CreatedAt,
@ -232,7 +236,7 @@ marshal(
} = Withdrawal
) ->
SesID = maps:get(session_id, Withdrawal, undefined),
#wthadpt_Withdrawal{
#wthd_provider_Withdrawal{
id = ID,
session_id = SesID,
body = marshal(body, Cash),
@ -245,7 +249,7 @@ marshal(transaction_info, TrxInfo) ->
ff_dmsl_codec:marshal(transaction_info, TrxInfo).
try_encode_proof_document({rus_domestic_passport, Token}, Acc) ->
[{rus_domestic_passport, #wthdm_RUSDomesticPassport{token = Token}} | Acc];
[{rus_domestic_passport, #wthd_domain_RUSDomesticPassport{token = Token}} | Acc];
try_encode_proof_document(_, Acc) ->
Acc.
@ -254,18 +258,18 @@ try_encode_proof_document(_, Acc) ->
-spec unmarshal(ff_codec:type_name(), ff_codec:encoded_value()) -> ff_codec:decoded_value().
unmarshal(adapter_state, ASt) ->
unmarshal_msgpack(ASt);
unmarshal(body, #wthadpt_Cash{
unmarshal(body, #wthd_provider_Cash{
amount = Amount,
currency = DomainCurrency
}) ->
CurrencyID = ff_currency:id(unmarshal(currency, DomainCurrency)),
{Amount, CurrencyID};
unmarshal(callback, #wthadpt_Callback{
unmarshal(callback, #wthd_provider_Callback{
tag = Tag,
payload = Payload
}) ->
#{tag => Tag, payload => Payload};
unmarshal(process_result, #wthadpt_ProcessResult{
unmarshal(process_result, #wthd_provider_ProcessResult{
intent = Intent,
next_state = NextState,
trx = TransactionInfo
@ -275,7 +279,7 @@ unmarshal(process_result, #wthadpt_ProcessResult{
next_state => maybe_unmarshal(adapter_state, NextState),
transaction_info => maybe_unmarshal(transaction_info, TransactionInfo)
});
unmarshal(callback_result, #wthadpt_CallbackResult{
unmarshal(callback_result, #wthd_provider_CallbackResult{
intent = Intent,
next_state = NextState,
response = Response,
@ -287,7 +291,7 @@ unmarshal(callback_result, #wthadpt_CallbackResult{
next_state => maybe_unmarshal(adapter_state, NextState),
transaction_info => maybe_unmarshal(transaction_info, TransactionInfo)
});
unmarshal(callback_response, #wthadpt_CallbackResponse{payload = Payload}) ->
unmarshal(callback_response, #wthd_provider_CallbackResponse{payload = Payload}) ->
#{payload => Payload};
unmarshal(currency, #domain_Currency{
name = Name,
@ -316,13 +320,17 @@ unmarshal(identity, _NotImplemented) ->
unmarshal(identity_documents, _NotImplemented) ->
%@TODO
erlang:error(not_implemented);
unmarshal(intent, {finish, #wthadpt_FinishIntent{status = {success, #wthadpt_Success{trx_info = undefined}}}}) ->
unmarshal(
intent, {finish, #wthd_provider_FinishIntent{status = {success, #wthd_provider_Success{trx_info = undefined}}}}
) ->
{finish, success};
unmarshal(intent, {finish, #wthadpt_FinishIntent{status = {success, #wthadpt_Success{trx_info = TrxInfo}}}}) ->
unmarshal(
intent, {finish, #wthd_provider_FinishIntent{status = {success, #wthd_provider_Success{trx_info = TrxInfo}}}}
) ->
{finish, {success, unmarshal(transaction_info, TrxInfo)}};
unmarshal(intent, {finish, #wthadpt_FinishIntent{status = {failure, Failure}}}) ->
unmarshal(intent, {finish, #wthd_provider_FinishIntent{status = {failure, Failure}}}) ->
{finish, {failed, ff_dmsl_codec:unmarshal(failure, Failure)}};
unmarshal(intent, {sleep, #wthadpt_SleepIntent{timer = Timer, callback_tag = Tag}}) ->
unmarshal(intent, {sleep, #wthd_provider_SleepIntent{timer = Timer, callback_tag = Tag}}) ->
{sleep,
genlib_map:compact(#{
timer => ff_codec:unmarshal(timer, Timer),
@ -334,7 +342,7 @@ unmarshal(process_callback_result, _NotImplemented) ->
unmarshal(quote_params, _NotImplemented) ->
%@TODO
erlang:error(not_implemented);
unmarshal(quote, #wthadpt_Quote{
unmarshal(quote, #wthd_provider_Quote{
cash_from = CashFrom,
cash_to = CashTo,
created_at = CreatedAt,

View File

@ -0,0 +1,216 @@
-module(ff_limiter).
-include_lib("damsel/include/dmsl_base_thrift.hrl").
-include_lib("damsel/include/dmsl_domain_thrift.hrl").
-include_lib("damsel/include/dmsl_wthd_domain_thrift.hrl").
-include_lib("limiter_proto/include/limproto_limiter_thrift.hrl").
-include_lib("limiter_proto/include/limproto_context_withdrawal_thrift.hrl").
-type turnover_selector() :: dmsl_domain_thrift:'TurnoverLimitSelector'().
-type turnover_limit() :: dmsl_domain_thrift:'TurnoverLimit'().
-type turnover_limit_upper_boundary() :: dmsl_domain_thrift:'Amount'().
-type domain_withdrawal() :: dmsl_wthd_domain_thrift:'Withdrawal'().
-type withdrawal() :: ff_withdrawal:withdrawal_state().
-type route() :: ff_withdrawal_routing:route().
-type limit() :: limproto_limiter_thrift:'Limit'().
-type limit_id() :: limproto_limiter_thrift:'LimitID'().
-type limit_change() :: limproto_limiter_thrift:'LimitChange'().
-type limit_amount() :: dmsl_domain_thrift:'Amount'().
-type context() :: limproto_limiter_thrift:'LimitContext'().
-type clock() :: limproto_limiter_thrift:'Clock'().
-export([get_turnover_limits/1]).
-export([check_limits/2]).
-export([marshal_withdrawal/1]).
-export([hold_withdrawal_limits/3]).
-export([commit_withdrawal_limits/3]).
-export([rollback_withdrawal_limits/3]).
-spec get_turnover_limits(turnover_selector() | undefined) -> [turnover_limit()].
get_turnover_limits(undefined) ->
[];
get_turnover_limits({value, Limits}) ->
Limits;
get_turnover_limits(Ambiguous) ->
error({misconfiguration, {'Could not reduce selector to a value', Ambiguous}}).
-spec check_limits([turnover_limit()], withdrawal()) ->
{ok, [limit()]}
| {error, {overflow, [{limit_id(), limit_amount(), turnover_limit_upper_boundary()}]}}.
check_limits(TurnoverLimits, Withdrawal) ->
Context = gen_limit_context(Withdrawal),
case lists:foldl(fun(Limit, Acc) -> check_limits_(Limit, Acc, Context) end, {[], []}, TurnoverLimits) of
{Limits, ErrorList} when length(ErrorList) =:= 0 ->
{ok, Limits};
{_, ErrorList} ->
{error, {overflow, ErrorList}}
end.
check_limits_(T, {Limits, Errors}, Context) ->
#domain_TurnoverLimit{id = LimitID} = T,
Clock = get_latest_clock(),
Limit = get(LimitID, Clock, Context),
#limiter_Limit{
amount = LimitAmount
} = Limit,
UpperBoundary = T#domain_TurnoverLimit.upper_boundary,
case LimitAmount =< UpperBoundary of
true ->
{[Limit | Limits], Errors};
false ->
{Limits, [{LimitID, LimitAmount, UpperBoundary} | Errors]}
end.
-spec hold_withdrawal_limits([turnover_limit()], route(), withdrawal()) -> ok.
hold_withdrawal_limits(TurnoverLimits, Route, Withdrawal) ->
IDs = [T#domain_TurnoverLimit.id || T <- TurnoverLimits],
LimitChanges = gen_limit_changes(IDs, Route, Withdrawal),
Context = gen_limit_context(Withdrawal),
hold(LimitChanges, get_latest_clock(), Context).
-spec commit_withdrawal_limits([turnover_limit()], route(), withdrawal()) -> ok.
commit_withdrawal_limits(TurnoverLimits, Route, Withdrawal) ->
IDs = [T#domain_TurnoverLimit.id || T <- TurnoverLimits],
LimitChanges = gen_limit_changes(IDs, Route, Withdrawal),
Context = gen_limit_context(Withdrawal),
commit(LimitChanges, get_latest_clock(), Context).
-spec rollback_withdrawal_limits([turnover_limit()], route(), withdrawal()) -> ok.
rollback_withdrawal_limits(TurnoverLimits, Route, Withdrawal) ->
IDs = [T#domain_TurnoverLimit.id || T <- TurnoverLimits],
LimitChanges = gen_limit_changes(IDs, Route, Withdrawal),
Context = gen_limit_context(Withdrawal),
rollback(LimitChanges, get_latest_clock(), Context).
-spec hold([limit_change()], clock(), context()) -> ok.
hold(LimitChanges, Clock, Context) ->
lists:foreach(
fun(LimitChange) ->
call_hold(LimitChange, Clock, Context)
end,
LimitChanges
).
-spec commit([limit_change()], clock(), context()) -> ok.
commit(LimitChanges, Clock, Context) ->
lists:foreach(
fun(LimitChange) ->
call_commit(LimitChange, Clock, Context)
end,
LimitChanges
).
-spec rollback([limit_change()], clock(), context()) -> ok.
rollback(LimitChanges, Clock, Context) ->
lists:foreach(
fun(LimitChange) ->
call_rollback(LimitChange, Clock, Context)
end,
LimitChanges
).
gen_limit_context(Withdrawal) ->
MarshaledWithdrawal = marshal_withdrawal(Withdrawal),
#limiter_LimitContext{
withdrawal_processing = #context_withdrawal_Context{
op = {withdrawal, #context_withdrawal_OperationWithdrawal{}},
withdrawal = #context_withdrawal_Withdrawal{withdrawal = MarshaledWithdrawal}
}
}.
gen_limit_changes(LimitIDs, Route, Withdrawal) ->
[
#limiter_LimitChange{
id = ID,
change_id = construct_limit_change_id(ID, Route, Withdrawal)
}
|| ID <- LimitIDs
].
construct_limit_change_id(LimitID, #{terminal_id := TerminalID, provider_id := ProviderID}, Withdrawal) ->
ComplexID = construct_complex_id([
LimitID,
genlib:to_binary(ProviderID),
genlib:to_binary(TerminalID),
ff_withdrawal:id(Withdrawal)
]),
genlib_string:join($., [<<"limiter">>, ComplexID]).
get_latest_clock() ->
{latest, #limiter_LatestClock{}}.
-spec construct_complex_id([binary()]) -> binary().
construct_complex_id(IDs) ->
genlib_string:join($., IDs).
-spec marshal_withdrawal(withdrawal()) -> domain_withdrawal().
marshal_withdrawal(Withdrawal) ->
#{
wallet_id := WalletID,
destination_id := DestinationID
} = ff_withdrawal:params(Withdrawal),
{ok, WalletMachine} = ff_wallet_machine:get(WalletID),
Wallet = ff_wallet_machine:wallet(WalletMachine),
WalletAccount = ff_wallet:account(Wallet),
{ok, DestinationMachine} = ff_destination_machine:get(DestinationID),
Destination = ff_destination_machine:destination(DestinationMachine),
DestinationAccount = ff_destination:account(Destination),
{ok, SenderSt} = ff_identity_machine:get(ff_account:identity(WalletAccount)),
{ok, ReceiverSt} = ff_identity_machine:get(ff_account:identity(DestinationAccount)),
SenderIdentity = ff_identity_machine:identity(SenderSt),
ReceiverIdentity = ff_identity_machine:identity(ReceiverSt),
Resource = ff_withdrawal:destination_resource(Withdrawal),
MarshaledResource = ff_adapter_withdrawal_codec:marshal(resource, Resource),
#wthd_domain_Withdrawal{
created_at = ff_codec:marshal(timestamp_ms, ff_withdrawal:created_at(Withdrawal)),
body = ff_dmsl_codec:marshal(cash, ff_withdrawal:body(Withdrawal)),
destination = MarshaledResource,
sender = ff_adapter_withdrawal_codec:marshal(identity, #{
id => ff_identity:id(SenderIdentity),
owner_id => ff_identity:party(SenderIdentity)
}),
receiver = ff_adapter_withdrawal_codec:marshal(identity, #{
id => ff_identity:id(ReceiverIdentity),
owner_id => ff_identity:party(SenderIdentity)
})
}.
-spec get(limit_id(), clock(), context()) -> limit() | no_return().
get(LimitID, Clock, Context) ->
Args = {LimitID, Clock, Context},
case call('Get', Args) of
{ok, Limit} ->
Limit;
{exception, #limiter_LimitNotFound{}} ->
error({not_found, LimitID});
{exception, #base_InvalidRequest{errors = Errors}} ->
error({invalid_request, Errors})
end.
-spec call_hold(limit_change(), clock(), context()) -> clock().
call_hold(LimitChange, Clock, Context) ->
Args = {LimitChange, Clock, Context},
{ok, ClockUpdated} = call('Hold', Args),
ClockUpdated.
-spec call_commit(limit_change(), clock(), context()) -> clock().
call_commit(LimitChange, Clock, Context) ->
Args = {LimitChange, Clock, Context},
{ok, ClockUpdated} = call('Commit', Args),
ClockUpdated.
-spec call_rollback(limit_change(), clock(), context()) -> clock().
call_rollback(LimitChange, Clock, Context) ->
Args = {LimitChange, Clock, Context},
{ok, ClockUpdated} = call('Rollback', Args),
ClockUpdated.
call(Func, Args) ->
Service = {limproto_limiter_thrift, 'Limiter'},
Request = {Service, Func, Args},
ff_woody_client:call(limiter, Request).

View File

@ -10,7 +10,8 @@
machinery,
machinery_extra,
damsel,
fistful
fistful,
limiter_proto
]},
{env, []},
{modules, []},

View File

@ -4,8 +4,7 @@
-module(ff_withdrawal).
-include_lib("damsel/include/dmsl_payment_processing_thrift.hrl").
-include_lib("damsel/include/dmsl_withdrawals_provider_adapter_thrift.hrl").
-include_lib("damsel/include/dmsl_domain_thrift.hrl").
-type id() :: binary().
@ -211,6 +210,7 @@
-export([domain_revision/1]).
-export([destination_resource/1]).
-export([metadata/1]).
-export([params/1]).
%% API
@ -300,8 +300,8 @@
| limit_check
| {fail, fail_type()}
| adjustment
| rollback_routing
% Legacy activity
| stop
| finish.
-type fail_type() ::
@ -380,6 +380,10 @@ created_at(T) ->
metadata(T) ->
maps:get(metadata, T, undefined).
-spec params(withdrawal_state()) -> transfer_params().
params(#{params := V}) ->
V.
%% API
-spec gen(gen_args()) -> withdrawal().
@ -596,10 +600,6 @@ do_start_adjustment(Params, Withdrawal) ->
update_attempts(Attempts, T) ->
maps:put(attempts, Attempts, T).
-spec params(withdrawal_state()) -> transfer_params().
params(#{params := V}) ->
V.
-spec p_transfer(withdrawal_state()) -> p_transfer() | undefined.
p_transfer(Withdrawal) ->
ff_withdrawal_route_attempt_utils:get_current_p_transfer(attempts(Withdrawal)).
@ -708,15 +708,8 @@ do_pending_activity(#{p_transfer := cancelled, session := failed}) ->
do_finished_activity(#{active_adjustment := true}) ->
adjustment;
%% Legacy activity. Remove after first deployment
do_finished_activity(#{status := {failed, _}, p_transfer := prepared}) ->
p_transfer_cancel;
do_finished_activity(#{status := succeeded, p_transfer := prepared}) ->
p_transfer_commit;
do_finished_activity(#{status := succeeded, p_transfer := committed}) ->
stop;
do_finished_activity(#{status := {failed, _}, p_transfer := cancelled}) ->
stop.
do_finished_activity(#{status := {failed, _}}) ->
rollback_routing.
-spec do_process_transfer(activity(), withdrawal_state()) -> process_result().
do_process_transfer(routing, Withdrawal) ->
@ -724,14 +717,17 @@ do_process_transfer(routing, Withdrawal) ->
do_process_transfer(p_transfer_start, Withdrawal) ->
process_p_transfer_creation(Withdrawal);
do_process_transfer(p_transfer_prepare, Withdrawal) ->
ok = do_rollback_routing(route(Withdrawal), Withdrawal),
Tr = ff_withdrawal_route_attempt_utils:get_current_p_transfer(attempts(Withdrawal)),
{ok, Events} = ff_postings_transfer:prepare(Tr),
{continue, [{p_transfer, Ev} || Ev <- Events]};
do_process_transfer(p_transfer_commit, Withdrawal) ->
ok = commit_routes_limits([route(Withdrawal)], Withdrawal),
Tr = ff_withdrawal_route_attempt_utils:get_current_p_transfer(attempts(Withdrawal)),
{ok, Events} = ff_postings_transfer:commit(Tr),
{continue, [{p_transfer, Ev} || Ev <- Events]};
do_process_transfer(p_transfer_cancel, Withdrawal) ->
ok = rollback_routes_limits([route(Withdrawal)], Withdrawal),
Tr = ff_withdrawal_route_attempt_utils:get_current_p_transfer(attempts(Withdrawal)),
{ok, Events} = ff_postings_transfer:cancel(Tr),
{continue, [{p_transfer, Ev} || Ev <- Events]};
@ -747,45 +743,39 @@ do_process_transfer(finish, Withdrawal) ->
process_transfer_finish(Withdrawal);
do_process_transfer(adjustment, Withdrawal) ->
process_adjustment(Withdrawal);
do_process_transfer(stop, _Withdrawal) ->
{undefined, []}.
do_process_transfer(rollback_routing, Withdrawal) ->
process_rollback_routing(Withdrawal).
-spec process_routing(withdrawal_state()) -> process_result().
process_routing(Withdrawal) ->
case do_process_routing(Withdrawal) of
{ok, [Route | _]} ->
{ok, [Route | _Rest]} ->
{continue, [
{route_changed, Route}
]};
{error, route_not_found} ->
process_transfer_fail(route_not_found, Withdrawal);
Events = process_transfer_fail(route_not_found, Withdrawal),
{continue, Events};
{error, {inconsistent_quote_route, _Data} = Reason} ->
process_transfer_fail(Reason, Withdrawal)
Events = process_transfer_fail(Reason, Withdrawal),
{continue, Events}
end.
-spec process_rollback_routing(withdrawal_state()) -> process_result().
process_rollback_routing(Withdrawal) ->
_ = do_rollback_routing(undefined, Withdrawal),
{undefined, []}.
-spec do_process_routing(withdrawal_state()) -> {ok, [route()]} | {error, Reason} when
Reason :: route_not_found | InconsistentQuote,
InconsistentQuote :: {inconsistent_quote_route, {provider_id, provider_id()} | {terminal_id, terminal_id()}}.
do_process_routing(Withdrawal) ->
WalletID = wallet_id(Withdrawal),
{ok, Wallet} = get_wallet(WalletID),
DomainRevision = operation_domain_revision(Withdrawal),
{ok, Destination} = get_destination(destination_id(Withdrawal)),
Resource = destination_resource(Withdrawal),
Identity = get_wallet_identity(Wallet),
PartyID = ff_identity:party(get_wallet_identity(Wallet)),
VarsetParams = genlib_map:compact(#{
body => body(Withdrawal),
wallet_id => WalletID,
wallet => Wallet,
party_id => PartyID,
destination => Destination,
resource => Resource
}),
do(fun() ->
Varset = build_party_varset(VarsetParams),
Routes = unwrap(ff_withdrawal_routing:prepare_routes(Varset, Identity, DomainRevision)),
{Varset, Context} = make_routing_varset_and_context(Withdrawal),
GatherResult = ff_withdrawal_routing:gather_routes(Varset, Context),
FilterResult = ff_withdrawal_routing:filter_limit_overflow_routes(GatherResult, Varset, Context),
ff_withdrawal_routing:log_reject_context(FilterResult),
Routes = unwrap(ff_withdrawal_routing:routes(FilterResult)),
case quote(Withdrawal) of
undefined ->
Routes;
@ -796,6 +786,57 @@ do_process_routing(Withdrawal) ->
end
end).
do_rollback_routing(ExcludeRoute, Withdrawal) ->
{Varset, Context} = make_routing_varset_and_context(Withdrawal),
{ok, Routes} = ff_withdrawal_routing:routes(ff_withdrawal_routing:gather_routes(Varset, Context)),
RollbackRoutes =
case ExcludeRoute of
undefined ->
Routes;
#{terminal_id := TerminalID} ->
lists:filter(
fun(#{terminal_id := TID}) ->
TerminalID =/= TID
end,
Routes
)
end,
rollback_routes_limits(RollbackRoutes, Varset, Context).
rollback_routes_limits(Routes, Withdrawal) ->
{Varset, Context} = make_routing_varset_and_context(Withdrawal),
rollback_routes_limits(Routes, Varset, Context).
rollback_routes_limits(Routes, Varset, Context) ->
ff_withdrawal_routing:rollback_routes_limits(Routes, Varset, Context).
commit_routes_limits(Routes, Withdrawal) ->
{Varset, Context} = make_routing_varset_and_context(Withdrawal),
ff_withdrawal_routing:commit_routes_limits(Routes, Varset, Context).
make_routing_varset_and_context(Withdrawal) ->
DomainRevision = operation_domain_revision(Withdrawal),
WalletID = wallet_id(Withdrawal),
{ok, Wallet} = get_wallet(WalletID),
{ok, Destination} = get_destination(destination_id(Withdrawal)),
Resource = destination_resource(Withdrawal),
PartyID = ff_identity:party(get_wallet_identity(Wallet)),
VarsetParams = genlib_map:compact(#{
body => body(Withdrawal),
wallet_id => WalletID,
wallet => Wallet,
party_id => PartyID,
destination => Destination,
resource => Resource
}),
Identity = get_wallet_identity(Wallet),
Context = #{
domain_revision => DomainRevision,
identity => Identity,
withdrawal => Withdrawal
},
{build_party_varset(VarsetParams), Context}.
-spec validate_quote_route(route(), quote_state()) -> {ok, valid} | {error, InconsistentQuote} when
InconsistentQuote :: {inconsistent_quote_route, {provider_id, provider_id()} | {terminal_id, terminal_id()}}.
validate_quote_route(Route, #{route := QuoteRoute}) ->
@ -932,10 +973,10 @@ process_session_sleep(Withdrawal) ->
process_transfer_finish(_Withdrawal) ->
{undefined, [{status_changed, succeeded}]}.
-spec process_transfer_fail(fail_type(), withdrawal_state()) -> process_result().
-spec process_transfer_fail(fail_type(), withdrawal_state()) -> [event()].
process_transfer_fail(FailType, Withdrawal) ->
Failure = build_failure(FailType, Withdrawal),
{undefined, [{status_changed, {failed, Failure}}]}.
[{status_changed, {failed, Failure}}].
-spec handle_child_result(process_result(), withdrawal_state()) -> process_result().
handle_child_result({undefined, Events} = Result, Withdrawal) ->
@ -1238,6 +1279,7 @@ get_quote_(Params) ->
} = Params,
Resource = maps:get(resource, Params, undefined),
%% TODO: don't apply turnover limits here
[Route | _] = unwrap(route, ff_withdrawal_routing:prepare_routes(Varset, Identity, DomainRevision)),
{Adapter, AdapterOpts} = ff_withdrawal_session:get_adapter_with_opts(Route),
GetQuoteParams = #{
@ -1588,7 +1630,8 @@ process_route_change(Withdrawal, Reason) ->
{ok, Providers} = do_process_routing(Withdrawal),
do_process_route_change(Providers, Withdrawal, Reason);
false ->
process_transfer_fail(Reason, Withdrawal)
Events = process_transfer_fail(Reason, Withdrawal),
{undefined, Events}
end.
-spec is_failure_transient(fail_type(), withdrawal_state()) -> boolean().
@ -1663,10 +1706,12 @@ do_process_route_change(Routes, Withdrawal, Reason) ->
]};
{error, route_not_found} ->
%% No more routes, return last error
process_transfer_fail(Reason, Withdrawal);
Events = process_transfer_fail(Reason, Withdrawal),
{continue, Events};
{error, attempt_limit_exceeded} ->
%% Attempt limit exceeded, return last error
process_transfer_fail(Reason, Withdrawal)
Events = process_transfer_fail(Reason, Withdrawal),
{continue, Events}
end.
-spec handle_adjustment_changes(ff_adjustment:changes()) -> [event()].

View File

@ -2,32 +2,49 @@
-include_lib("damsel/include/dmsl_domain_thrift.hrl").
-export([prepare_routes/2]).
-export([prepare_routes/3]).
-export([gather_routes/2]).
-export([filter_limit_overflow_routes/3]).
-export([rollback_routes_limits/3]).
-export([commit_routes_limits/3]).
-export([make_route/2]).
-export([get_provider/1]).
-export([get_terminal/1]).
-export([provision_terms/2]).
-export([merge_withdrawal_terms/2]).
-export([routes/1]).
-export([log_reject_context/1]).
-import(ff_pipeline, [do/1, unwrap/1]).
-type route() :: #{
version := 1,
provider_id := provider_id(),
terminal_id => terminal_id(),
terminal_id := terminal_id(),
provider_id_legacy => provider_id()
}.
-type routing_context() :: #{
domain_revision := domain_revision(),
identity := identity(),
withdrawal => withdrawal()
}.
-type routing_state() :: #{
routes := [routing_rule_route()],
reject_context := reject_context()
}.
-export_type([route/0]).
-export_type([routing_context/0]).
-type identity() :: ff_identity:identity_state().
-type withdrawal() :: ff_withdrawal:withdrawal_state().
-type domain_revision() :: ff_domain_config:revision().
-type party_varset() :: ff_varset:varset().
-type provider_ref() :: ff_payouts_provider:provider_ref().
-type provider_id() :: ff_payouts_provider:id().
-type terminal_ref() :: ff_payouts_terminal:terminal_ref().
-type terminal_id() :: ff_payouts_terminal:id().
-type routing_rule_route() :: ff_routing_rule:route().
@ -36,27 +53,70 @@
-type withdrawal_provision_terms() :: dmsl_domain_thrift:'WithdrawalProvisionTerms'().
-type currency_selector() :: dmsl_domain_thrift:'CurrencySelector'().
-type cash_limit_selector() :: dmsl_domain_thrift:'CashLimitSelector'().
-type turnover_limit_selector() :: dmsl_domain_thrift:'TurnoverLimitSelector'().
-type process_route_fun() :: fun(
(withdrawal_provision_terms(), party_varset(), route(), routing_context()) ->
ok
| {ok, valid}
| {error, Error :: term()}
).
%%
-spec prepare_routes(party_varset(), identity(), domain_revision()) -> {ok, [route()]} | {error, route_not_found}.
-spec prepare_routes(party_varset(), identity(), domain_revision()) ->
{ok, [route()]} | {error, route_not_found}.
prepare_routes(PartyVarset, Identity, DomainRevision) ->
prepare_routes(PartyVarset, #{identity => Identity, domain_revision => DomainRevision}).
-spec prepare_routes(party_varset(), routing_context()) ->
{ok, [route()]} | {error, route_not_found}.
prepare_routes(PartyVarset, Context) ->
State = gather_routes(PartyVarset, Context),
log_reject_context(State),
routes(State).
-spec gather_routes(party_varset(), routing_context()) ->
routing_state().
gather_routes(PartyVarset, Context = #{identity := Identity, domain_revision := DomainRevision}) ->
{ok, PaymentInstitutionID} = ff_party:get_identity_payment_institution_id(Identity),
{ok, PaymentInstitution} = ff_payment_institution:get(PaymentInstitutionID, PartyVarset, DomainRevision),
{Routes, RejectContext0} = ff_routing_rule:gather_routes(
{Routes, RejectContext} = ff_routing_rule:gather_routes(
PaymentInstitution,
withdrawal_routing_rules,
PartyVarset,
DomainRevision
),
{ValidatedRoutes, RejectContext1} = filter_valid_routes(Routes, RejectContext0, PartyVarset, DomainRevision),
case ValidatedRoutes of
[_ | _] ->
{ok, ValidatedRoutes};
[] ->
ff_routing_rule:log_reject_context(RejectContext1),
{error, route_not_found}
end.
filter_valid_routes(#{routes => Routes, reject_context => RejectContext}, PartyVarset, Context).
-spec filter_limit_overflow_routes(routing_state(), party_varset(), routing_context()) ->
routing_state().
filter_limit_overflow_routes(State, PartyVarset, RoutingContext) ->
validate_routes_with(
fun do_validate_limits/4,
State,
PartyVarset,
RoutingContext
).
-spec rollback_routes_limits([route()], party_varset(), routing_context()) ->
ok.
rollback_routes_limits(Routes, PartyVarset, RoutingContext) ->
process_routes_with(
fun do_rollback_limits/4,
Routes,
PartyVarset,
RoutingContext
).
-spec commit_routes_limits([route()], party_varset(), routing_context()) ->
ok.
commit_routes_limits(Routes, PartyVarset, RoutingContext) ->
process_routes_with(
fun do_commit_limits/4,
Routes,
PartyVarset,
RoutingContext
).
-spec make_route(provider_id(), terminal_id() | undefined) -> route().
make_route(ProviderID, TerminalID) ->
@ -74,21 +134,6 @@ get_provider(#{provider_id := ProviderID}) ->
get_terminal(Route) ->
maps:get(terminal_id, Route, undefined).
-spec provision_terms(route(), domain_revision()) -> ff_maybe:maybe(withdrawal_provision_terms()).
provision_terms(Route, DomainRevision) ->
ProviderID = get_provider(Route),
{ok, Provider} = ff_payouts_provider:get(ProviderID, DomainRevision),
ProviderTerms = ff_payouts_provider:provision_terms(Provider),
TerminalTerms =
case get_terminal(Route) of
undefined ->
undefined;
TerminalID ->
{ok, Terminal} = ff_payouts_terminal:get(TerminalID, DomainRevision),
ff_payouts_terminal:provision_terms(Terminal)
end,
merge_withdrawal_terms(ProviderTerms, TerminalTerms).
-spec merge_withdrawal_terms(
ff_payouts_provider:provision_terms() | undefined,
ff_payouts_terminal:provision_terms() | undefined
@ -116,58 +161,138 @@ merge_withdrawal_terms(
merge_withdrawal_terms(ProviderTerms, TerminalTerms) ->
ff_maybe:get_defined(TerminalTerms, ProviderTerms).
-spec routes(routing_state()) ->
{ok, [route()]} | {error, route_not_found}.
routes(#{routes := Routes = [_ | _]}) ->
{ok, sort_routes(Routes)};
routes(_) ->
{error, route_not_found}.
-spec sort_routes([routing_rule_route()]) -> [route()].
sort_routes(RoutingRuleRoutes) ->
ProviderTerminalMap = lists:foldl(
fun(#{provider_ref := ProviderRef, terminal_ref := TerminalRef, priority := Priority}, Acc0) ->
TerminalID = TerminalRef#domain_TerminalRef.id,
ProviderID = ProviderRef#domain_ProviderRef.id,
Routes = maps:get(Priority, Acc0, []),
Acc1 = maps:put(Priority, [{ProviderID, TerminalID} | Routes], Acc0),
Acc1
end,
#{},
RoutingRuleRoutes
),
lists:foldl(
fun({_, Data}, Acc) ->
SortedRoutes = [make_route(P, T) || {P, T} <- lists:sort(Data)],
SortedRoutes ++ Acc
end,
[],
lists:keysort(1, maps:to_list(ProviderTerminalMap))
).
-spec log_reject_context(routing_state()) ->
ok.
log_reject_context(#{reject_context := RejectContext}) ->
ff_routing_rule:log_reject_context(RejectContext).
%%
-spec filter_valid_routes([routing_rule_route()], reject_context(), party_varset(), domain_revision()) ->
{[route()], reject_context()}.
filter_valid_routes(Routes, RejectContext, PartyVarset, DomainRevision) ->
filter_valid_routes_(Routes, PartyVarset, {#{}, RejectContext}, DomainRevision).
-spec filter_valid_routes(routing_state(), party_varset(), routing_context()) ->
routing_state().
filter_valid_routes(State, PartyVarset, RoutingContext) ->
validate_routes_with(
fun do_validate_terms/4,
State,
PartyVarset,
RoutingContext
).
filter_valid_routes_([], _, {Acc, RejectContext}, _DomainRevision) when map_size(Acc) == 0 ->
{[], RejectContext};
filter_valid_routes_([], _, {Acc, RejectContext}, _DomainRevision) ->
{convert_to_route(Acc), RejectContext};
filter_valid_routes_([Route | Rest], PartyVarset, {Acc0, RejectContext0}, DomainRevision) ->
Terminal = maps:get(terminal, Route),
TerminalRef = maps:get(terminal_ref, Route),
TerminalID = TerminalRef#domain_TerminalRef.id,
ProviderRef = Terminal#domain_Terminal.provider_ref,
ProviderID = ProviderRef#domain_ProviderRef.id,
Priority = maps:get(priority, Route, undefined),
{Acc, RejectContext} =
case validate_terms(ProviderRef, TerminalRef, PartyVarset, DomainRevision) of
{ok, valid} ->
Terms = maps:get(Priority, Acc0, []),
Acc1 = maps:put(Priority, [{ProviderID, TerminalID} | Terms], Acc0),
{Acc1, RejectContext0};
{error, RejectReason} ->
RejectedRoutes0 = maps:get(rejected_routes, RejectContext0),
RejectedRoutes1 = [{ProviderRef, TerminalRef, RejectReason} | RejectedRoutes0],
RejectContext1 = maps:put(rejected_routes, RejectedRoutes1, RejectContext0),
{Acc0, RejectContext1}
-spec process_routes_with(process_route_fun(), [route()], party_varset(), routing_context()) ->
ok.
process_routes_with(Func, Routes, PartyVarset, RoutingContext) ->
lists:foreach(
fun(Route) ->
ProviderID = maps:get(provider_id, Route),
TerminalID = maps:get(terminal_id, Route),
ProviderRef = #domain_ProviderRef{id = ProviderID},
TerminalRef = #domain_TerminalRef{id = TerminalID},
get_route_terms_and_process(Func, ProviderRef, TerminalRef, PartyVarset, RoutingContext)
end,
filter_valid_routes_(Rest, PartyVarset, {Acc, RejectContext}, DomainRevision).
Routes
).
-spec validate_terms(provider_ref(), terminal_ref(), party_varset(), domain_revision()) ->
{ok, valid}
| {error, Error :: term()}.
validate_terms(ProviderRef, TerminalRef, PartyVarset, DomainRevision) ->
-spec validate_routes_with(
process_route_fun(), routing_state(), party_varset(), routing_context()
) ->
routing_state().
validate_routes_with(Func, #{routes := Routes, reject_context := RejectContext}, PartyVarset, RoutingContext) ->
lists:foldl(
fun(Route, State = #{routes := ValidRoutes0, reject_context := RejectContext0}) ->
ProviderRef = maps:get(provider_ref, Route),
TerminalRef = maps:get(terminal_ref, Route),
case get_route_terms_and_process(Func, ProviderRef, TerminalRef, PartyVarset, RoutingContext) of
{ok, valid} ->
ValidRoutes1 = [Route | ValidRoutes0],
State#{routes => ValidRoutes1};
{error, RejectReason} ->
RejectedRoutes0 = maps:get(rejected_routes, RejectContext0),
RejectedRoutes1 = [{ProviderRef, TerminalRef, RejectReason} | RejectedRoutes0],
RejectContext1 = maps:put(rejected_routes, RejectedRoutes1, RejectContext0),
State#{reject_context => RejectContext1}
end
end,
#{routes => [], reject_context => RejectContext},
Routes
).
get_route_terms_and_process(
Func, ProviderRef, TerminalRef, PartyVarset, RoutingContext = #{domain_revision := DomainRevision}
) ->
case ff_party:compute_provider_terminal_terms(ProviderRef, TerminalRef, PartyVarset, DomainRevision) of
{ok, #domain_ProvisionTermSet{
wallet = #domain_WalletProvisionTerms{
withdrawals = WithdrawalProvisionTerms
}
}} ->
do_validate_terms(WithdrawalProvisionTerms, PartyVarset);
Route = make_route(ProviderRef#domain_ProviderRef.id, TerminalRef#domain_TerminalRef.id),
Func(WithdrawalProvisionTerms, PartyVarset, Route, RoutingContext);
{error, Error} ->
%% TODO: test for provision_termset_undefined error after routing migration
{error, Error}
end.
-spec do_validate_terms(withdrawal_provision_terms(), party_varset()) ->
-spec do_rollback_limits(withdrawal_provision_terms(), party_varset(), route(), routing_context()) ->
ok.
do_rollback_limits(CombinedTerms, _PartyVarset, Route, #{withdrawal := Withdrawal}) ->
#domain_WithdrawalProvisionTerms{
turnover_limit = TurnoverLimit
} = CombinedTerms,
Limits = ff_limiter:get_turnover_limits(TurnoverLimit),
ff_limiter:rollback_withdrawal_limits(Limits, Route, Withdrawal).
-spec do_commit_limits(withdrawal_provision_terms(), party_varset(), route(), routing_context()) ->
ok.
do_commit_limits(CombinedTerms, _PartyVarset, Route, #{withdrawal := Withdrawal}) ->
#domain_WithdrawalProvisionTerms{
turnover_limit = TurnoverLimit
} = CombinedTerms,
Limits = ff_limiter:get_turnover_limits(TurnoverLimit),
ff_limiter:commit_withdrawal_limits(Limits, Route, Withdrawal).
-spec do_validate_limits(withdrawal_provision_terms(), party_varset(), route(), routing_context()) ->
{ok, valid}
| {error, Error :: term()}.
do_validate_terms(CombinedTerms, PartyVarset) ->
do_validate_limits(CombinedTerms, PartyVarset, Route, RoutingContext) ->
do(fun() ->
#domain_WithdrawalProvisionTerms{
turnover_limit = TurnoverLimits
} = CombinedTerms,
valid = unwrap(validate_turnover_limits(TurnoverLimits, PartyVarset, Route, RoutingContext))
end).
-spec do_validate_terms(withdrawal_provision_terms(), party_varset(), route(), routing_context()) ->
{ok, valid}
| {error, Error :: term()}.
do_validate_terms(CombinedTerms, PartyVarset, _Route, _RoutingContext) ->
do(fun() ->
#domain_WithdrawalProvisionTerms{
currencies = CurrenciesSelector,
@ -224,15 +349,21 @@ validate_cash_limit({value, CashRange}, #{cost := Cash}) ->
validate_cash_limit(_NotReducedSelector, _VS) ->
{error, {misconfiguration, {not_reduced_termset, cash_range}}}.
convert_to_route(ProviderTerminalMap) ->
lists:foldl(
fun({_, Data}, Acc) ->
SortedRoutes = [make_route(P, T) || {P, T} <- lists:sort(Data)],
SortedRoutes ++ Acc
end,
[],
lists:keysort(1, maps:to_list(ProviderTerminalMap))
).
-spec validate_turnover_limits(turnover_limit_selector(), party_varset(), route(), routing_context()) ->
{ok, valid}
| {error, Error :: term()}.
validate_turnover_limits(undefined, _VS, _Route, _RoutingContext) ->
{ok, valid};
validate_turnover_limits({value, TurnoverLimits}, _VS, Route, #{withdrawal := Withdrawal}) ->
ok = ff_limiter:hold_withdrawal_limits(TurnoverLimits, Route, Withdrawal),
case ff_limiter:check_limits(TurnoverLimits, Withdrawal) of
{ok, _} ->
{ok, valid};
{error, Error} ->
{error, {terms_violation, Error}}
end;
validate_turnover_limits(NotReducedSelector, _VS, _Route, _RoutingContext) ->
{error, {misconfiguration, {'Could not reduce selector to a value', NotReducedSelector}}}.
%% TESTS
@ -245,7 +376,7 @@ convert_to_route(ProviderTerminalMap) ->
convert_to_route_test() ->
?assertEqual(
[],
convert_to_route(#{})
sort_routes([])
),
?assertEqual(
[
@ -255,11 +386,33 @@ convert_to_route_test() ->
#{provider_id => 200, terminal_id => 2101, version => 1},
#{provider_id => 300, terminal_id => 2200, version => 1}
],
convert_to_route(#{
1000 => [{100, 2000}, {100, 2001}],
900 => [{200, 2100}, {200, 2101}],
100 => [{300, 2200}]
})
sort_routes([
#{
provider_ref => #domain_ProviderRef{id = 100},
terminal_ref => #domain_TerminalRef{id = 2000},
priority => 1000
},
#{
provider_ref => #domain_ProviderRef{id = 100},
terminal_ref => #domain_TerminalRef{id = 2001},
priority => 1000
},
#{
provider_ref => #domain_ProviderRef{id = 200},
terminal_ref => #domain_TerminalRef{id = 2100},
priority => 900
},
#{
provider_ref => #domain_ProviderRef{id = 200},
terminal_ref => #domain_TerminalRef{id = 2101},
priority => 900
},
#{
provider_ref => #domain_ProviderRef{id = 300},
terminal_ref => #domain_TerminalRef{id = 2200},
priority => 100
}
])
).
-endif.

View File

@ -0,0 +1,59 @@
-module(ff_ct_limiter_client).
-include_lib("limiter_proto/include/limproto_limiter_thrift.hrl").
-export([get/3]).
-export([create_config/2]).
-export([get_config/2]).
-type client() :: woody_context:ctx().
-type limit_id() :: limproto_limiter_thrift:'LimitID'().
-type limit_context() :: limproto_limiter_thrift:'LimitContext'().
-type clock() :: limproto_limiter_thrift:'Clock'().
-type limit_config_params() :: limproto_config_thrift:'LimitConfigParams'().
%%% API
-spec get(limit_id(), limit_context(), client()) -> woody:result() | no_return().
get(LimitID, Context, Client) ->
call('Get', {LimitID, clock(), Context}, Client).
-spec create_config(limit_config_params(), client()) -> woody:result() | no_return().
create_config(LimitCreateParams, Client) ->
call_configurator('Create', {LimitCreateParams}, Client).
-spec get_config(limit_id(), client()) -> woody:result() | no_return().
get_config(LimitConfigID, Client) ->
call_configurator('Get', {LimitConfigID}, Client).
%%% Internal functions
-spec call(atom(), tuple(), client()) -> woody:result() | no_return().
call(Function, Args, Client) ->
Call = {{limproto_limiter_thrift, 'Limiter'}, Function, Args},
Opts = #{
url => <<"http://limiter:8022/v1/limiter">>,
event_handler => scoper_woody_event_handler,
transport_opts => #{
max_connections => 10000
}
},
woody_client:call(Call, Opts, Client).
-spec call_configurator(atom(), tuple(), client()) -> woody:result() | no_return().
call_configurator(Function, Args, Client) ->
Call = {{limproto_configurator_thrift, 'Configurator'}, Function, Args},
Opts = #{
url => <<"http://limiter:8022/v1/configurator">>,
event_handler => scoper_woody_event_handler,
transport_opts => #{
max_connections => 10000
}
},
woody_client:call(Call, Opts, Client).
-spec clock() -> clock().
clock() ->
{vector, #limiter_VectorClock{state = <<>>}}.

View File

@ -1,7 +1,8 @@
-module(ff_deposit_SUITE).
-include_lib("stdlib/include/assert.hrl").
-include_lib("damsel/include/dmsl_payment_processing_thrift.hrl").
-include_lib("damsel/include/dmsl_domain_thrift.hrl").
-include_lib("damsel/include/dmsl_payproc_thrift.hrl").
%% Common test API

View File

@ -1,6 +1,6 @@
-module(ff_destination_SUITE).
-include_lib("fistful_proto/include/ff_proto_destination_thrift.hrl").
-include_lib("fistful_proto/include/fistful_destination_thrift.hrl").
-include_lib("damsel/include/dmsl_domain_thrift.hrl").
-include_lib("stdlib/include/assert.hrl").

View File

@ -0,0 +1,89 @@
-module(ff_limiter_helper).
-include_lib("limiter_proto/include/limproto_limiter_thrift.hrl").
-include_lib("limiter_proto/include/limproto_context_withdrawal_thrift.hrl").
-include_lib("limiter_proto/include/limproto_config_thrift.hrl").
-include_lib("limiter_proto/include/limproto_timerange_thrift.hrl").
-include_lib("damsel/include/dmsl_wthd_domain_thrift.hrl").
-include_lib("ff_cth/include/ct_domain.hrl").
-export([init_per_suite/1]).
-export([get_limit_amount/3]).
-export([get_limit/3]).
-type withdrawal() :: ff_withdrawal:withdrawal_state() | dmsl_wthd_domain_thrift:'Withdrawal'().
-type limit() :: limproto_limiter_thrift:'Limit'().
-type config() :: ct_suite:ct_config().
-type id() :: binary().
-spec init_per_suite(config()) -> _.
init_per_suite(Config) ->
{ok, #config_LimitConfig{}} = ff_ct_limiter_client:create_config(
limiter_create_num_params(?LIMIT_TURNOVER_NUM_PAYTOOL_ID1),
ct_helper:get_woody_ctx(Config)
),
{ok, #config_LimitConfig{}} = ff_ct_limiter_client:create_config(
limiter_create_num_params(?LIMIT_TURNOVER_NUM_PAYTOOL_ID2),
ct_helper:get_woody_ctx(Config)
),
{ok, #config_LimitConfig{}} = ff_ct_limiter_client:create_config(
limiter_create_amount_params(?LIMIT_TURNOVER_AMOUNT_PAYTOOL_ID1),
ct_helper:get_woody_ctx(Config)
),
{ok, #config_LimitConfig{}} = ff_ct_limiter_client:create_config(
limiter_create_amount_params(?LIMIT_TURNOVER_AMOUNT_PAYTOOL_ID2),
ct_helper:get_woody_ctx(Config)
).
-spec get_limit_amount(id(), withdrawal(), config()) -> integer().
get_limit_amount(LimitID, Withdrawal, Config) ->
#limiter_Limit{amount = Amount} = get_limit(LimitID, Withdrawal, Config),
Amount.
-spec get_limit(id(), withdrawal(), config()) -> limit().
get_limit(LimitId, Withdrawal, Config) ->
MarshaledWithdrawal = maybe_marshal_withdrawal(Withdrawal),
Context = #limiter_LimitContext{
withdrawal_processing = #context_withdrawal_Context{
op = {withdrawal, #context_withdrawal_OperationWithdrawal{}},
withdrawal = #context_withdrawal_Withdrawal{withdrawal = MarshaledWithdrawal}
}
},
{ok, Limit} = ff_ct_limiter_client:get(LimitId, Context, ct_helper:get_woody_ctx(Config)),
Limit.
maybe_marshal_withdrawal(Withdrawal = #wthd_domain_Withdrawal{}) ->
Withdrawal;
maybe_marshal_withdrawal(Withdrawal) ->
ff_limiter:marshal_withdrawal(Withdrawal).
limiter_create_num_params(LimitID) ->
#config_LimitConfigParams{
id = LimitID,
started_at = <<"2000-01-01T00:00:00Z">>,
shard_size = 12,
time_range_type = {calendar, {month, #timerange_TimeRangeTypeCalendarMonth{}}},
context_type = {withdrawal_processing, #config_LimitContextTypeWithdrawalProcessing{}},
type = {turnover, #config_LimitTypeTurnover{}},
scope = {single, {payment_tool, #config_LimitScopeEmptyDetails{}}},
description = <<"description">>,
op_behaviour = #config_OperationLimitBehaviour{
invoice_payment_refund = {subtraction, #config_Subtraction{}}
}
}.
limiter_create_amount_params(LimitID) ->
#config_LimitConfigParams{
id = LimitID,
started_at = <<"2000-01-01T00:00:00Z">>,
shard_size = 12,
time_range_type = {calendar, {month, #timerange_TimeRangeTypeCalendarMonth{}}},
context_type = {withdrawal_processing, #config_LimitContextTypeWithdrawalProcessing{}},
type =
{turnover, #config_LimitTypeTurnover{metric = {amount, #config_LimitTurnoverAmount{currency = <<"RUB">>}}}},
scope = {single, {party, #config_LimitScopeEmptyDetails{}}},
description = <<"description">>,
op_behaviour = #config_OperationLimitBehaviour{
invoice_payment_refund = {subtraction, #config_Subtraction{}}
}
}.

View File

@ -1,6 +1,6 @@
-module(ff_source_SUITE).
-include_lib("fistful_proto/include/ff_proto_source_thrift.hrl").
-include_lib("fistful_proto/include/fistful_source_thrift.hrl").
-include_lib("damsel/include/dmsl_domain_thrift.hrl").
-include_lib("stdlib/include/assert.hrl").

View File

@ -1,7 +1,10 @@
-module(ff_transfer_SUITE).
-include_lib("fistful_proto/include/ff_proto_fistful_admin_thrift.hrl").
-include_lib("fistful_proto/include/ff_proto_withdrawal_thrift.hrl").
-include_lib("fistful_proto/include/fistful_fistful_base_thrift.hrl").
-include_lib("fistful_proto/include/fistful_admin_thrift.hrl").
-include_lib("fistful_proto/include/fistful_wthd_thrift.hrl").
-include_lib("fistful_proto/include/fistful_source_thrift.hrl").
-include_lib("fistful_proto/include/fistful_deposit_thrift.hrl").
-export([all/0]).
-export([groups/0]).
@ -113,22 +116,22 @@ deposit_via_admin_ok(C) ->
{ok, Src1} = call_admin(
'CreateSource',
{
#ff_admin_SourceParams{
#admin_SourceParams{
id = SrcID,
name = <<"HAHA NO">>,
identity_id = IID,
currency = #'fistful_base_CurrencyRef'{symbolic_code = <<"RUB">>},
resource = {internal, #src_Internal{details = <<"Infinite source of cash">>}}
resource = {internal, #source_Internal{details = <<"Infinite source of cash">>}}
}
}
),
SrcID = Src1#src_Source.id,
{authorized, #src_Authorized{}} = ct_helper:await(
{authorized, #src_Authorized{}},
SrcID = Src1#source_Source.id,
{authorized, #source_Authorized{}} = ct_helper:await(
{authorized, #source_Authorized{}},
fun() ->
{ok, Src} = call_admin('GetSource', {SrcID}),
Src#src_Source.status
Src#source_Source.status
end
),
@ -136,7 +139,7 @@ deposit_via_admin_ok(C) ->
{ok, Dep1} = call_admin(
'CreateDeposit',
{
#ff_admin_DepositParams{
#admin_DepositParams{
id = DepID,
source = SrcID,
destination = WalID,
@ -171,29 +174,29 @@ deposit_via_admin_fails(C) ->
{ok, Src1} = call_admin(
'CreateSource',
{
#ff_admin_SourceParams{
#admin_SourceParams{
id = SrcID,
name = <<"HAHA NO">>,
identity_id = IID,
currency = #'fistful_base_CurrencyRef'{symbolic_code = <<"RUB">>},
resource = {internal, #src_Internal{details = <<"Infinite source of cash">>}}
resource = {internal, #source_Internal{details = <<"Infinite source of cash">>}}
}
}
),
SrcID = Src1#src_Source.id,
{authorized, #src_Authorized{}} = ct_helper:await(
{authorized, #src_Authorized{}},
SrcID = Src1#source_Source.id,
{authorized, #source_Authorized{}} = ct_helper:await(
{authorized, #source_Authorized{}},
fun() ->
{ok, Src} = call_admin('GetSource', {SrcID}),
Src#src_Source.status
Src#source_Source.status
end
),
{ok, Dep1} = call_admin(
'CreateDeposit',
{
#ff_admin_DepositParams{
#admin_DepositParams{
id = DepID,
source = SrcID,
destination = WalID,
@ -230,28 +233,28 @@ deposit_via_admin_amount_fails(C) ->
{ok, _Src1} = call_admin(
'CreateSource',
{
#ff_admin_SourceParams{
#admin_SourceParams{
id = SrcID,
name = <<"HAHA NO">>,
identity_id = IID,
currency = #'fistful_base_CurrencyRef'{symbolic_code = <<"RUB">>},
resource = {internal, #src_Internal{details = <<"Infinite source of cash">>}}
resource = {internal, #source_Internal{details = <<"Infinite source of cash">>}}
}
}
),
{authorized, #src_Authorized{}} = ct_helper:await(
{authorized, #src_Authorized{}},
{authorized, #source_Authorized{}} = ct_helper:await(
{authorized, #source_Authorized{}},
fun() ->
{ok, Src} = call_admin('GetSource', {SrcID}),
Src#src_Source.status
Src#source_Source.status
end
),
{exception, #ff_admin_DepositAmountInvalid{}} = call_admin(
{exception, #admin_DepositAmountInvalid{}} = call_admin(
'CreateDeposit',
{
#ff_admin_DepositParams{
#admin_DepositParams{
id = DepID,
source = SrcID,
destination = WalID,
@ -275,29 +278,29 @@ deposit_via_admin_currency_fails(C) ->
{ok, Src1} = call_admin(
'CreateSource',
{
#ff_admin_SourceParams{
#admin_SourceParams{
id = SrcID,
name = <<"HAHA NO">>,
identity_id = IID,
currency = #'fistful_base_CurrencyRef'{symbolic_code = <<"RUB">>},
resource = {internal, #src_Internal{details = <<"Infinite source of cash">>}}
resource = {internal, #source_Internal{details = <<"Infinite source of cash">>}}
}
}
),
SrcID = Src1#src_Source.id,
{authorized, #src_Authorized{}} = ct_helper:await(
{authorized, #src_Authorized{}},
SrcID = Src1#source_Source.id,
{authorized, #source_Authorized{}} = ct_helper:await(
{authorized, #source_Authorized{}},
fun() ->
{ok, Src} = call_admin('GetSource', {SrcID}),
Src#src_Source.status
Src#source_Source.status
end
),
BadCurrency = <<"CAT">>,
{exception, #ff_admin_DepositCurrencyInvalid{}} = call_admin(
{exception, #admin_DepositCurrencyInvalid{}} = call_admin(
'CreateDeposit',
{
#ff_admin_DepositParams{
#admin_DepositParams{
id = DepID,
source = SrcID,
destination = WalID,
@ -466,7 +469,7 @@ generate_id() ->
genlib:to_binary(genlib_time:ticks()).
call_admin(Fun, Args) ->
Service = {ff_proto_fistful_admin_thrift, 'FistfulAdmin'},
Service = {fistful_admin_thrift, 'FistfulAdmin'},
Request = {Service, Fun, Args},
Client = ff_woody_client:new(#{
url => <<"http://localhost:8022/v1/admin">>,
@ -602,7 +605,7 @@ process_withdrawal(WalID, DestID, Params) ->
%%%
get_withdrawal_events(WdrID) ->
Service = {{ff_proto_withdrawal_thrift, 'Management'}, <<"/v1/withdrawal">>},
Service = {{fistful_wthd_thrift, 'Management'}, <<"/v1/withdrawal">>},
{ok, Events} = call('GetEvents', Service, {WdrID, #'fistful_base_EventRange'{'after' = 0, limit = 1000}}),
Events.

View File

@ -1,10 +1,12 @@
-module(ff_withdrawal_SUITE).
-include_lib("stdlib/include/assert.hrl").
-include_lib("fistful_proto/include/fistful_fistful_base_thrift.hrl").
-include_lib("ff_cth/include/ct_domain.hrl").
-include_lib("damsel/include/dmsl_domain_thrift.hrl").
-include_lib("fistful_proto/include/ff_proto_withdrawal_session_thrift.hrl").
-include_lib("fistful_proto/include/ff_proto_withdrawal_thrift.hrl").
-include_lib("fistful_proto/include/fistful_wthd_session_thrift.hrl").
-include_lib("fistful_proto/include/fistful_wthd_thrift.hrl").
-include_lib("fistful_proto/include/fistful_wthd_status_thrift.hrl").
-include_lib("fistful_proto/include/fistful_repairer_thrift.hrl").
%% Common test API
@ -651,9 +653,9 @@ force_status_change_test(C) ->
}}
}}
],
action = #ff_repairer_ComplexAction{
action = #repairer_ComplexAction{
timer =
{set_timer, #ff_repairer_SetTimerAction{
{set_timer, #repairer_SetTimerAction{
timer = {timeout, 10000}
}}
}
@ -1043,7 +1045,7 @@ repair_withdrawal_session(WithdrawalID) ->
ok.
call_session_repair(SessionID, Scenario) ->
Service = {ff_proto_withdrawal_session_thrift, 'Repairer'},
Service = {fistful_wthd_session_thrift, 'Repairer'},
Request = {Service, 'Repair', {SessionID, Scenario}},
Client = ff_woody_client:new(#{
url => <<"http://localhost:8022/v1/repair/withdrawal/session">>,
@ -1052,7 +1054,7 @@ call_session_repair(SessionID, Scenario) ->
ff_woody_client:call(Client, Request).
call_withdrawal_repair(SessionID, Scenario) ->
Service = {ff_proto_withdrawal_thrift, 'Repairer'},
Service = {fistful_wthd_thrift, 'Repairer'},
Request = {Service, 'Repair', {SessionID, Scenario}},
Client = ff_woody_client:new(#{
url => <<"http://localhost:8022/v1/repair/withdrawal">>,

View File

@ -0,0 +1,375 @@
-module(ff_withdrawal_limits_SUITE).
-include_lib("stdlib/include/assert.hrl").
-include_lib("fistful_proto/include/fistful_fistful_base_thrift.hrl").
-include_lib("ff_cth/include/ct_domain.hrl").
-include_lib("damsel/include/dmsl_wthd_domain_thrift.hrl").
%% Common test API
-export([all/0]).
-export([groups/0]).
-export([init_per_suite/1]).
-export([end_per_suite/1]).
-export([init_per_group/2]).
-export([end_per_group/2]).
-export([init_per_testcase/2]).
-export([end_per_testcase/2]).
%% Tests
-export([limit_success/1]).
-export([limit_overflow/1]).
-export([choose_provider_without_limit_overflow/1]).
-export([provider_limits_exhaust_orderly/1]).
%% Internal types
-type config() :: ct_helper:config().
-type test_case_name() :: ct_helper:test_case_name().
-type group_name() :: ct_helper:group_name().
-type test_return() :: _ | no_return().
%% API
-spec all() -> [test_case_name() | {group, group_name()}].
all() ->
[
{group, default}
].
-spec groups() -> [{group_name(), list(), [test_case_name()]}].
groups() ->
[
{default, [sequence], [
limit_success,
limit_overflow,
choose_provider_without_limit_overflow,
provider_limits_exhaust_orderly
]}
].
-spec init_per_suite(config()) -> config().
init_per_suite(C0) ->
C1 = ct_helper:makeup_cfg(
[
ct_helper:test_case_name(init),
ct_payment_system:setup()
],
C0
),
_ = ff_limiter_helper:init_per_suite(C1),
C1.
-spec end_per_suite(config()) -> _.
end_per_suite(C) ->
ok = ct_payment_system:shutdown(C).
%%
-spec init_per_group(group_name(), config()) -> config().
init_per_group(_, C) ->
C.
-spec end_per_group(group_name(), config()) -> _.
end_per_group(_, _) ->
ok.
%%
-spec init_per_testcase(test_case_name(), config()) -> config().
init_per_testcase(Name, C) ->
C1 = ct_helper:makeup_cfg(
[
ct_helper:test_case_name(Name),
ct_helper:woody_ctx()
],
C
),
ok = ct_helper:set_context(C1),
C1.
-spec end_per_testcase(test_case_name(), config()) -> _.
end_per_testcase(_Name, _C) ->
ok = ct_helper:unset_context().
%% Tests
-spec limit_success(config()) -> test_return().
limit_success(C) ->
Cash = {800800, <<"RUB">>},
#{
wallet_id := WalletID,
destination_id := DestinationID
} = prepare_standard_environment(Cash, C),
WithdrawalID = generate_id(),
WithdrawalParams = #{
id => WithdrawalID,
destination_id => DestinationID,
wallet_id => WalletID,
body => Cash,
external_id => WithdrawalID
},
PreviousAmount = get_limit_amount(Cash, WalletID, DestinationID, ?LIMIT_TURNOVER_NUM_PAYTOOL_ID1, C),
ok = ff_withdrawal_machine:create(WithdrawalParams, ff_entity_context:new()),
?assertEqual(succeeded, await_final_withdrawal_status(WithdrawalID)),
Withdrawal = get_withdrawal(WithdrawalID),
?assertEqual(
PreviousAmount + 1, ff_limiter_helper:get_limit_amount(?LIMIT_TURNOVER_NUM_PAYTOOL_ID1, Withdrawal, C)
).
-spec limit_overflow(config()) -> test_return().
limit_overflow(C) ->
Cash = {900900, <<"RUB">>},
#{
wallet_id := WalletID,
destination_id := DestinationID
} = prepare_standard_environment(Cash, C),
WithdrawalID = generate_id(),
WithdrawalParams = #{
id => WithdrawalID,
destination_id => DestinationID,
wallet_id => WalletID,
body => Cash,
external_id => WithdrawalID
},
PreviousAmount = get_limit_amount(Cash, WalletID, DestinationID, ?LIMIT_TURNOVER_NUM_PAYTOOL_ID2, C),
ok = ff_withdrawal_machine:create(WithdrawalParams, ff_entity_context:new()),
Result = await_final_withdrawal_status(WithdrawalID),
?assertMatch({failed, #{code := <<"no_route_found">>}}, Result),
%% we get final withdrawal status before we rollback limits so wait for it some amount of time
ok = timer:sleep(500),
Withdrawal = get_withdrawal(WithdrawalID),
?assertEqual(PreviousAmount, ff_limiter_helper:get_limit_amount(?LIMIT_TURNOVER_NUM_PAYTOOL_ID2, Withdrawal, C)).
-spec choose_provider_without_limit_overflow(config()) -> test_return().
choose_provider_without_limit_overflow(C) ->
Cash = {901000, <<"RUB">>},
#{
wallet_id := WalletID,
destination_id := DestinationID
} = prepare_standard_environment(Cash, C),
WithdrawalID = generate_id(),
WithdrawalParams = #{
id => WithdrawalID,
destination_id => DestinationID,
wallet_id => WalletID,
body => Cash,
external_id => WithdrawalID
},
PreviousAmount = get_limit_amount(Cash, WalletID, DestinationID, ?LIMIT_TURNOVER_NUM_PAYTOOL_ID2, C),
ok = ff_withdrawal_machine:create(WithdrawalParams, ff_entity_context:new()),
?assertEqual(succeeded, await_final_withdrawal_status(WithdrawalID)),
Withdrawal = get_withdrawal(WithdrawalID),
?assertEqual(
PreviousAmount + 1, ff_limiter_helper:get_limit_amount(?LIMIT_TURNOVER_NUM_PAYTOOL_ID2, Withdrawal, C)
).
-spec provider_limits_exhaust_orderly(config()) -> test_return().
provider_limits_exhaust_orderly(C) ->
Currency = <<"RUB">>,
Cash1 = {902000, Currency},
Cash2 = {903000, Currency},
%% we don't want to overflow wallet cash limit
TotalCash = {3000000, Currency},
#{
wallet_id := WalletID,
destination_id := DestinationID
} = prepare_standard_environment(TotalCash, C),
%% First withdrawal goes to limit 1 and spents half of its amount
WithdrawalID1 = generate_id(),
WithdrawalParams1 = #{
id => WithdrawalID1,
destination_id => DestinationID,
wallet_id => WalletID,
body => Cash1,
external_id => WithdrawalID1
},
0 = get_limit_amount(Cash1, WalletID, DestinationID, ?LIMIT_TURNOVER_AMOUNT_PAYTOOL_ID1, C),
ok = ff_withdrawal_machine:create(WithdrawalParams1, ff_entity_context:new()),
?assertEqual(succeeded, await_final_withdrawal_status(WithdrawalID1)),
Withdrawal1 = get_withdrawal(WithdrawalID1),
?assertEqual(902000, ff_limiter_helper:get_limit_amount(?LIMIT_TURNOVER_AMOUNT_PAYTOOL_ID1, Withdrawal1, C)),
%% Second withdrawal goes to limit 2 as limit 1 doesn't have enough and spents all its amount
WithdrawalID2 = generate_id(),
WithdrawalParams2 = #{
id => WithdrawalID2,
destination_id => DestinationID,
wallet_id => WalletID,
body => Cash2,
external_id => WithdrawalID2
},
0 = get_limit_amount(Cash2, WalletID, DestinationID, ?LIMIT_TURNOVER_AMOUNT_PAYTOOL_ID2, C),
ok = ff_withdrawal_machine:create(WithdrawalParams2, ff_entity_context:new()),
?assertEqual(succeeded, await_final_withdrawal_status(WithdrawalID2)),
Withdrawal2 = get_withdrawal(WithdrawalID2),
?assertEqual(903000, ff_limiter_helper:get_limit_amount(?LIMIT_TURNOVER_AMOUNT_PAYTOOL_ID2, Withdrawal2, C)),
%% Third withdrawal goes to limit 1 and spents all its amount
WithdrawalID3 = generate_id(),
WithdrawalParams3 = #{
id => WithdrawalID3,
destination_id => DestinationID,
wallet_id => WalletID,
body => Cash1,
external_id => WithdrawalID3
},
902000 = get_limit_amount(Cash1, WalletID, DestinationID, ?LIMIT_TURNOVER_AMOUNT_PAYTOOL_ID1, C),
ok = ff_withdrawal_machine:create(WithdrawalParams3, ff_entity_context:new()),
?assertEqual(succeeded, await_final_withdrawal_status(WithdrawalID3)),
Withdrawal3 = get_withdrawal(WithdrawalID3),
?assertEqual(1804000, ff_limiter_helper:get_limit_amount(?LIMIT_TURNOVER_AMOUNT_PAYTOOL_ID1, Withdrawal3, C)),
%% Last withdrawal can't find route cause all limits are drained
WithdrawalID = generate_id(),
WithdrawalParams = #{
id => WithdrawalID,
destination_id => DestinationID,
wallet_id => WalletID,
body => Cash1,
external_id => WithdrawalID
},
ok = ff_withdrawal_machine:create(WithdrawalParams, ff_entity_context:new()),
Result = await_final_withdrawal_status(WithdrawalID),
?assertMatch({failed, #{code := <<"no_route_found">>}}, Result).
%% Utils
get_limit_amount(Cash, WalletID, DestinationID, LimitID, C) ->
{ok, WalletMachine} = ff_wallet_machine:get(WalletID),
Wallet = ff_wallet_machine:wallet(WalletMachine),
WalletAccount = ff_wallet:account(Wallet),
{ok, SenderSt} = ff_identity_machine:get(ff_account:identity(WalletAccount)),
SenderIdentity = ff_identity_machine:identity(SenderSt),
Withdrawal = #wthd_domain_Withdrawal{
created_at = ff_codec:marshal(timestamp_ms, ff_time:now()),
body = ff_dmsl_codec:marshal(cash, Cash),
destination = ff_adapter_withdrawal_codec:marshal(resource, get_destination_resource(DestinationID)),
sender = ff_adapter_withdrawal_codec:marshal(identity, #{
id => ff_identity:id(SenderIdentity),
owner_id => ff_identity:party(SenderIdentity)
})
},
ff_limiter_helper:get_limit_amount(LimitID, Withdrawal, C).
get_destination_resource(DestinationID) ->
{ok, DestinationMachine} = ff_destination_machine:get(DestinationID),
Destination = ff_destination_machine:destination(DestinationMachine),
{ok, Resource} = ff_resource:create_resource(ff_destination:resource(Destination)),
Resource.
prepare_standard_environment({_Amount, Currency} = WithdrawalCash, C) ->
Party = create_party(C),
IdentityID = create_person_identity(Party, C),
WalletID = create_wallet(IdentityID, <<"My wallet">>, Currency, C),
ok = await_wallet_balance({0, Currency}, WalletID),
DestinationID = create_destination(IdentityID, Currency, C),
ok = set_wallet_balance(WithdrawalCash, WalletID),
#{
identity_id => IdentityID,
party_id => Party,
wallet_id => WalletID,
destination_id => DestinationID
}.
get_withdrawal(WithdrawalID) ->
{ok, Machine} = ff_withdrawal_machine:get(WithdrawalID),
ff_withdrawal_machine:withdrawal(Machine).
get_withdrawal_status(WithdrawalID) ->
Withdrawal = get_withdrawal(WithdrawalID),
ff_withdrawal:status(Withdrawal).
await_final_withdrawal_status(WithdrawalID) ->
finished = ct_helper:await(
finished,
fun() ->
{ok, Machine} = ff_withdrawal_machine:get(WithdrawalID),
Withdrawal = ff_withdrawal_machine:withdrawal(Machine),
case ff_withdrawal:is_finished(Withdrawal) of
false ->
{not_finished, Withdrawal};
true ->
finished
end
end,
genlib_retry:linear(20, 1000)
),
get_withdrawal_status(WithdrawalID).
create_party(_C) ->
ID = genlib:bsuuid(),
_ = ff_party:create(ID),
ID.
create_person_identity(Party, C) ->
create_identity(Party, <<"good-one">>, C).
create_identity(Party, ProviderID, C) ->
create_identity(Party, <<"Identity Name">>, ProviderID, C).
create_identity(Party, Name, ProviderID, _C) ->
ID = genlib:unique(),
ok = ff_identity_machine:create(
#{id => ID, name => Name, party => Party, provider => ProviderID},
#{<<"com.rbkmoney.wapi">> => #{<<"name">> => Name}}
),
ID.
create_wallet(IdentityID, Name, Currency, _C) ->
ID = genlib:unique(),
ok = ff_wallet_machine:create(
#{id => ID, identity => IdentityID, name => Name, currency => Currency},
ff_entity_context:new()
),
ID.
await_wallet_balance({Amount, Currency}, ID) ->
Balance = {Amount, {{inclusive, Amount}, {inclusive, Amount}}, Currency},
Balance = ct_helper:await(
Balance,
fun() -> get_wallet_balance(ID) end,
genlib_retry:linear(3, 500)
),
ok.
get_wallet_balance(ID) ->
{ok, Machine} = ff_wallet_machine:get(ID),
get_account_balance(ff_wallet:account(ff_wallet_machine:wallet(Machine))).
get_account_balance(Account) ->
{ok, {Amounts, Currency}} = ff_accounting:balance(Account),
{ff_indef:current(Amounts), ff_indef:to_range(Amounts), Currency}.
generate_id() ->
ff_id:generate_snowflake_id().
create_destination(IID, Currency, C) ->
ID = generate_id(),
StoreSource = ct_cardstore:bank_card(<<"4150399999000900">>, {12, 2025}, C),
Resource = {bank_card, #{bank_card => StoreSource}},
Params = #{id => ID, identity => IID, name => <<"XDesination">>, currency => Currency, resource => Resource},
ok = ff_destination_machine:create(Params, ff_entity_context:new()),
authorized = ct_helper:await(
authorized,
fun() ->
{ok, Machine} = ff_destination_machine:get(ID),
Destination = ff_destination_machine:destination(Machine),
ff_destination:status(Destination)
end
),
ID.
set_wallet_balance({Amount, Currency}, ID) ->
TransactionID = generate_id(),
{ok, Machine} = ff_wallet_machine:get(ID),
Account = ff_wallet:account(ff_wallet_machine:wallet(Machine)),
AccounterID = ff_account:accounter_account_id(Account),
{CurrentAmount, _, Currency} = get_account_balance(Account),
{ok, AnotherAccounterID} = ct_helper:create_account(Currency),
Postings = [{AnotherAccounterID, AccounterID, {Amount - CurrentAmount, Currency}}],
{ok, _} = ff_accounting:prepare_trx(TransactionID, Postings),
{ok, _} = ff_accounting:commit_trx(TransactionID, Postings),
ok.

View File

@ -1,7 +1,7 @@
-module(ff_bin_data).
-include_lib("binbase_proto/include/binbase_binbase_thrift.hrl").
-include_lib("binbase_proto/include/binbase_msgpack_thrift.hrl").
-include_lib("msgpack_proto/include/msgp_msgpack_thrift.hrl").
-type token() :: binary().
-type issuer_country() :: atom().
@ -73,7 +73,7 @@ id(Data) ->
%%
encode_msgpack(nil) ->
{nl, #'binbase_Nil'{}};
{nl, #'msgpack_Nil'{}};
encode_msgpack(V) when is_boolean(V) ->
{b, V};
encode_msgpack(V) when is_integer(V) ->
@ -115,7 +115,7 @@ decode_result(Token, #'binbase_ResponseData'{bin_data = Bindata, version = Versi
})
end).
decode_msgpack({nl, #'binbase_Nil'{}}) ->
decode_msgpack({nl, #'msgpack_Nil'{}}) ->
nil;
decode_msgpack({b, V}) when is_boolean(V) ->
V;

View File

@ -1,6 +1,8 @@
-module(ff_cash_flow).
-include_lib("damsel/include/dmsl_payment_processing_thrift.hrl").
-include_lib("damsel/include/dmsl_base_thrift.hrl").
-include_lib("damsel/include/dmsl_domain_thrift.hrl").
-include_lib("damsel/include/dmsl_payproc_thrift.hrl").
-export([make_empty_final/0]).
-export([gather_used_accounts/1]).
@ -195,7 +197,7 @@ decode_rounding_method(RoundingMethod) ->
RoundingMethod.
-spec decode_rational(dmsl_base_thrift:'Rational'()) -> genlib_rational:t().
decode_rational(#'Rational'{p = P, q = Q}) ->
decode_rational(#'base_Rational'{p = P, q = Q}) ->
genlib_rational:new(P, Q).
-spec compute_volume(plan_volume(), constant_mapping()) -> {ok, cash()} | {error, volume_finalize_error()}.

View File

@ -1,6 +1,6 @@
-module(ff_clock).
-include_lib("fistful_proto/include/ff_proto_transfer_thrift.hrl").
-include_lib("fistful_proto/include/fistful_transfer_thrift.hrl").
-define(VERSION, 1).
-define(TYPE_LATEST, latest).
@ -30,14 +30,14 @@ latest_clock() ->
new(?TYPE_LATEST).
-spec marshal(kind(), clock()) ->
ff_proto_transfer_thrift:'Clock'().
fistful_transfer_thrift:'Clock'().
marshal(transfer, #{type := ?TYPE_LATEST = Type}) ->
{Type, #transfer_LatestClock{}};
marshal(transfer, #{type := ?TYPE_VECTOR = Type, state := State}) ->
{Type, #transfer_VectorClock{state = State}}.
-spec unmarshal(kind(), Clock) -> clock() when
Clock :: ff_proto_transfer_thrift:'Clock'().
Clock :: fistful_transfer_thrift:'Clock'().
unmarshal(transfer, {?TYPE_LATEST = Type, #transfer_LatestClock{}}) ->
new(Type);
unmarshal(transfer, {?TYPE_VECTOR = Type, #transfer_VectorClock{state = State}}) ->

View File

@ -1,5 +1,6 @@
-module(ff_dmsl_codec).
-include_lib("damsel/include/dmsl_base_thrift.hrl").
-include_lib("damsel/include/dmsl_domain_thrift.hrl").
-include_lib("damsel/include/dmsl_user_interaction_thrift.hrl").
@ -137,9 +138,12 @@ unmarshal(currency, #domain_Currency{
numcode => Numcode,
exponent => Exponent
};
unmarshal(user_interaction, {redirect, {get_request, #'BrowserGetRequest'{uri = URI}}}) ->
unmarshal(user_interaction, {redirect, {get_request, #'user_interaction_BrowserGetRequest'{uri = URI}}}) ->
{redirect, #{content => {get, URI}}};
unmarshal(user_interaction, {redirect, {post_request, #'BrowserPostRequest'{uri = URI, form = Form}}}) ->
unmarshal(
user_interaction,
{redirect, {post_request, #'user_interaction_BrowserPostRequest'{uri = URI, form = Form}}}
) ->
{redirect, #{content => {post, URI, Form}}};
unmarshal(
resource,
@ -353,7 +357,7 @@ marshal(attempt_limit, Limit) ->
attempts = Limit
};
marshal(content, #{type := Type, data := Data}) ->
#'Content'{
#'base_Content'{
type = marshal(string, Type),
data = Data
};

View File

@ -9,7 +9,7 @@
-export([head/0]).
-type revision() :: dmt_client:version().
-type object_data() :: dmt_client:object_data().
-type object_data() :: dmt_client:untagged_domain_object().
-type object_ref() :: dmsl_domain_thrift:'Reference'().
-export_type([revision/0]).
@ -18,7 +18,7 @@
%%
-include_lib("damsel/include/dmsl_domain_config_thrift.hrl").
-include_lib("damsel/include/dmsl_domain_conf_thrift.hrl").
-spec object(object_ref()) -> {ok, object_data()} | {error, notfound}.
object(ObjectRef) ->

View File

@ -8,7 +8,8 @@
-module(ff_party).
-include_lib("damsel/include/dmsl_payment_processing_thrift.hrl").
-include_lib("damsel/include/dmsl_domain_thrift.hrl").
-include_lib("damsel/include/dmsl_payproc_thrift.hrl").
-type id() :: dmsl_domain_thrift:'PartyID'().
-type contract_id() :: dmsl_domain_thrift:'ContractID'().

View File

@ -2,6 +2,7 @@
-include_lib("damsel/include/dmsl_domain_thrift.hrl").
-export([new_reject_context/1]).
-export([gather_routes/4]).
-export([log_reject_context/1]).
@ -10,7 +11,6 @@
-type provider_ref() :: dmsl_domain_thrift:'ProviderRef'().
-type provider() :: dmsl_domain_thrift:'Provider'().
-type terminal_ref() :: dmsl_domain_thrift:'TerminalRef'().
-type terminal() :: dmsl_domain_thrift:'Terminal'().
-type priority() :: integer().
-type weight() :: integer().
-type varset() :: ff_varset:varset().
@ -20,16 +20,14 @@
-type candidate_description() :: binary() | undefined.
-type route() :: #{
provider_ref := provider_ref(),
terminal_ref := terminal_ref(),
terminal := terminal(),
priority => priority(),
weight => weight(),
provider => provider()
priority := priority(),
weight => weight()
}.
-export_type([route/0]).
-export_type([provider/0]).
-export_type([terminal/0]).
-export_type([reject_context/0]).
-export_type([rejected_route/0]).
@ -46,12 +44,16 @@
%%
-spec gather_routes(payment_institution(), routing_rule_tag(), varset(), revision()) -> {[route()], reject_context()}.
gather_routes(PaymentInstitution, RoutingRuleTag, VS, Revision) ->
RejectContext = #{
-spec new_reject_context(varset()) -> reject_context().
new_reject_context(VS) ->
#{
varset => VS,
rejected_routes => []
},
}.
-spec gather_routes(payment_institution(), routing_rule_tag(), varset(), revision()) -> {[route()], reject_context()}.
gather_routes(PaymentInstitution, RoutingRuleTag, VS, Revision) ->
RejectContext = new_reject_context(VS),
case do_gather_routes(PaymentInstitution, RoutingRuleTag, VS, Revision) of
{ok, {AcceptedRoutes, RejectedRoutes}} ->
{AcceptedRoutes, RejectContext#{rejected_routes => RejectedRoutes}};
@ -117,13 +119,11 @@ filter_prohibited_candidates(Candidates, ProhibitedCandidates, Revision) ->
lists:foldr(
fun(C, {Accepted, Rejected}) ->
Route = make_route(C, Revision),
#{terminal_ref := TerminalRef} = Route,
#{provider_ref := ProviderRef, terminal_ref := TerminalRef} = Route,
case maps:find(TerminalRef, ProhibitionTable) of
error ->
{[Route | Accepted], Rejected};
{ok, Description} ->
#{terminal := Terminal} = Route,
ProviderRef = Terminal#domain_Terminal.provider_ref,
{Accepted, [{ProviderRef, TerminalRef, {'RoutingRule', Description}} | Rejected]}
end
end,
@ -146,13 +146,11 @@ make_route(Candidate, Revision) ->
Priority = Candidate#domain_RoutingCandidate.priority,
Weight = Candidate#domain_RoutingCandidate.weight,
ProviderRef = Terminal#domain_Terminal.provider_ref,
{ok, Provider} = ff_domain_config:object(Revision, {provider, ProviderRef}),
genlib_map:compact(#{
provider_ref => ProviderRef,
terminal_ref => TerminalRef,
terminal => Terminal,
priority => Priority,
weight => Weight,
provider => Provider
weight => Weight
}).
-spec log_reject_context(reject_context()) -> ok.

View File

@ -1,6 +1,7 @@
-module(ff_varset).
-include_lib("damsel/include/dmsl_payment_processing_thrift.hrl").
-include_lib("damsel/include/dmsl_domain_thrift.hrl").
-include_lib("damsel/include/dmsl_payproc_thrift.hrl").
-export_type([varset/0]).
-export_type([encoded_varset/0]).
@ -23,7 +24,7 @@
bin_data => dmsl_domain_thrift:'BinData'()
}.
-type encoded_varset() :: dmsl_payment_processing_thrift:'Varset'().
-type encoded_varset() :: dmsl_payproc_thrift:'Varset'().
-spec encode(varset()) -> encoded_varset().
encode(Varset) ->
@ -39,7 +40,7 @@ encode(Varset) ->
bin_data = genlib_map:get(bin_data, Varset)
}.
-spec encode_contract_terms_varset(varset()) -> dmsl_payment_processing_thrift:'ComputeContractTermsVarset'().
-spec encode_contract_terms_varset(varset()) -> dmsl_payproc_thrift:'ComputeContractTermsVarset'().
encode_contract_terms_varset(Varset) ->
#payproc_ComputeContractTermsVarset{
currency = genlib_map:get(currency, Varset),

View File

@ -13,11 +13,11 @@
%% Internal types
%%
-type destination() :: dmsl_withdrawals_domain_thrift:'Destination'().
-type identity() :: dmsl_withdrawals_domain_thrift:'Identity'().
-type destination() :: dmsl_wthd_domain_thrift:'Destination'().
-type identity() :: dmsl_wthd_domain_thrift:'Identity'().
-type cash() :: dmsl_domain_thrift:'Cash'().
-type currency() :: dmsl_domain_thrift:'Currency'().
-type domain_quote() :: dmsl_withdrawals_provider_adapter_thrift:'Quote'().
-type domain_quote() :: dmsl_wthd_provider_thrift:'Quote'().
-type withdrawal() :: #{
id => binary(),

View File

@ -1,6 +1,7 @@
-module(ff_ct_provider).
-include_lib("damsel/include/dmsl_withdrawals_provider_adapter_thrift.hrl").
-include_lib("damsel/include/dmsl_domain_thrift.hrl").
-include_lib("damsel/include/dmsl_wthd_provider_thrift.hrl").
%% API
-export([start/0]).
@ -18,11 +19,11 @@
%% Internal types
%%
-type destination() :: dmsl_withdrawals_domain_thrift:'Destination'().
-type identity() :: dmsl_withdrawals_domain_thrift:'Identity'().
-type destination() :: dmsl_wthd_domain_thrift:'Destination'().
-type identity() :: dmsl_wthd_domain_thrift:'Identity'().
-type cash() :: dmsl_domain_thrift:'Cash'().
-type currency() :: dmsl_domain_thrift:'Currency'().
-type domain_quote() :: dmsl_withdrawals_provider_adapter_thrift:'Quote'().
-type domain_quote() :: dmsl_wthd_provider_thrift:'Quote'().
-type withdrawal() :: #{
id => binary(),
@ -80,14 +81,14 @@ start(Opts) ->
next_state => state(),
transaction_info => transaction_info()
}}.
process_withdrawal(#{quote := #wthadpt_Quote{quote_data = QuoteData}}, State, _Options) when
process_withdrawal(#{quote := #wthd_provider_Quote{quote_data = QuoteData}}, State, _Options) when
QuoteData =:= ?DUMMY_QUOTE_ERROR
->
{ok, #{
intent => {finish, {failed, #{code => <<"test_error">>}}},
next_state => State
}};
process_withdrawal(#{quote := #wthadpt_Quote{quote_data = QuoteData}}, State, _Options) when
process_withdrawal(#{quote := #wthd_provider_Quote{quote_data = QuoteData}}, State, _Options) when
QuoteData =:= ?DUMMY_QUOTE
->
{ok, #{
@ -107,7 +108,7 @@ get_quote(
#{
currency_from := CurrencyFrom,
currency_to := CurrencyTo,
exchange_cash := #wthadpt_Cash{amount = Amount, currency = Currency}
exchange_cash := #wthd_provider_Cash{amount = Amount, currency = Currency}
},
_Options
) ->
@ -132,7 +133,7 @@ handle_callback(_Callback, _Withdrawal, _State, _Options) ->
erlang:error(not_implemented).
calc_cash(Currency, Currency, Amount) ->
#wthadpt_Cash{amount = Amount, currency = Currency};
#wthd_provider_Cash{amount = Amount, currency = Currency};
calc_cash(Currency, _, Amount) ->
NewAmount = erlang:round(Amount / 2),
#wthadpt_Cash{amount = NewAmount, currency = Currency}.
#wthd_provider_Cash{amount = NewAmount, currency = Currency}.

View File

@ -2,7 +2,8 @@
-behaviour(woody_server_thrift_handler).
-include_lib("damsel/include/dmsl_withdrawals_provider_adapter_thrift.hrl").
-include_lib("damsel/include/dmsl_domain_thrift.hrl").
-include_lib("damsel/include/dmsl_wthd_provider_thrift.hrl").
%% woody_server_thrift_handler callbacks
-export([handle_function/4]).
@ -22,7 +23,7 @@ handle_function('ProcessWithdrawal', {Withdrawal, InternalState, Options}, _Cont
#{intent := Intent} = ProcessResult,
NewState = maps:get(next_state, ProcessResult, undefined),
TransactionInfo = maps:get(transaction_info, ProcessResult, undefined),
{ok, #wthadpt_ProcessResult{
{ok, #wthd_provider_ProcessResult{
intent = encode_intent(Intent),
next_state = encode_state(NewState),
trx = encode_trx(TransactionInfo)
@ -43,7 +44,7 @@ handle_function('HandleCallback', {Callback, Withdrawal, InternalState, Options}
#{intent := Intent, response := Response} = CallbackResult,
NewState = maps:get(next_state, CallbackResult, undefined),
TransactionInfo = maps:get(transaction_info, CallbackResult, undefined),
{ok, #wthadpt_CallbackResult{
{ok, #wthd_provider_CallbackResult{
intent = encode_intent(Intent),
next_state = encode_state(NewState),
response = encode_callback_response(Response),
@ -54,7 +55,7 @@ handle_function('HandleCallback', {Callback, Withdrawal, InternalState, Options}
%% Internals
%%
decode_withdrawal(#wthadpt_Withdrawal{
decode_withdrawal(#wthd_provider_Withdrawal{
id = Id,
body = Body,
destination = Destination,
@ -71,7 +72,7 @@ decode_withdrawal(#wthadpt_Withdrawal{
quote => Quote
}.
decode_quote_params(#wthadpt_GetQuoteParams{
decode_quote_params(#wthd_provider_GetQuoteParams{
idempotency_id = IdempotencyID,
currency_from = CurrencyFrom,
currency_to = CurrencyTo,
@ -90,7 +91,7 @@ decode_options(Options) ->
decode_state(State) ->
ff_adapter_withdrawal_codec:unmarshal(adapter_state, State).
decode_callback(#wthadpt_Callback{tag = Tag, payload = Payload}) ->
decode_callback(#wthd_provider_Callback{tag = Tag, payload = Payload}) ->
#{tag => Tag, payload => Payload}.
%%
@ -111,7 +112,7 @@ encode_quote(#{
expires_on := ExpiresOn,
quote_data := QuoteData
}) ->
#wthadpt_Quote{
#wthd_provider_Quote{
cash_from = CashFrom,
cash_to = CashTo,
created_at = CreatedAt,
@ -120,7 +121,7 @@ encode_quote(#{
}.
encode_callback_response(#{payload := Payload}) ->
#wthadpt_CallbackResponse{payload = Payload}.
#wthd_provider_CallbackResponse{payload = Payload}.
get_handler(Opts) ->
proplists:get_value(handler, Opts, ff_ct_provider).

View File

@ -16,7 +16,7 @@ init(Opts) ->
ff_ct_provider_thrift_service_sup,
#{
handlers => [
{Path, {{dmsl_withdrawals_provider_adapter_thrift, 'Adapter'}, {ff_ct_provider_thrift, []}}}
{Path, {{dmsl_wthd_provider_thrift, 'Adapter'}, {ff_ct_provider_thrift, []}}}
],
event_handler => scoper_woody_event_handler,
ip => proplists:get_value(ip, Opts, "::"),

View File

@ -1,6 +1,7 @@
-module(ff_ct_sleepy_provider).
-include_lib("damsel/include/dmsl_withdrawals_provider_adapter_thrift.hrl").
-include_lib("damsel/include/dmsl_domain_thrift.hrl").
-include_lib("damsel/include/dmsl_wthd_provider_thrift.hrl").
%% API
-export([start/0]).
@ -15,11 +16,11 @@
%% Internal types
%%
-type destination() :: dmsl_withdrawals_domain_thrift:'Destination'().
-type identity() :: dmsl_withdrawals_domain_thrift:'Identity'().
-type destination() :: dmsl_wthd_domain_thrift:'Destination'().
-type identity() :: dmsl_wthd_domain_thrift:'Identity'().
-type cash() :: dmsl_domain_thrift:'Cash'().
-type currency() :: dmsl_domain_thrift:'Currency'().
-type domain_quote() :: dmsl_withdrawals_provider_adapter_thrift:'Quote'().
-type domain_quote() :: dmsl_wthd_provider_thrift:'Quote'().
-type withdrawal() :: #{
id => binary(),
@ -109,7 +110,7 @@ get_quote(_Quote, _Options) ->
next_state => state(),
transaction_info => transaction_info()
}}.
handle_callback(_Callback, #{quote := #wthadpt_Quote{quote_data = QuoteData}}, _State, _Options) when
handle_callback(_Callback, #{quote := #wthd_provider_Quote{quote_data = QuoteData}}, _State, _Options) when
QuoteData =:= ?DUMMY_QUOTE_ERROR_FATAL
->
erlang:error(spanish_inquisition);

Some files were not shown because too many files have changed in this diff Show More