@riocrypto/common-server 1.0.2912 → 1.0.2913
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/helpers/enablement-gate.d.ts +29 -0
- package/build/helpers/enablement-gate.js +29 -0
- package/build/helpers/payin-destinations.js +14 -1
- package/build/helpers/processor-enablement.js +11 -1
- package/build/helpers/resolve-processor.js +15 -14
- package/build/index.d.ts +1 -0
- package/build/index.js +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { ProcessorEnablementState } from "@riocrypto/common";
|
|
2
|
+
/**
|
|
3
|
+
* Whether silence about a rail should be read as a refusal, for one customer in
|
|
4
|
+
* one corridor and one direction.
|
|
5
|
+
*
|
|
6
|
+
* The setting alone is not enough to answer it. Accounts are seeded and shown for
|
|
7
|
+
* the country a customer onboarded in, while an order or a quote may name any
|
|
8
|
+
* corridor we support, so a corridor where they have accepted nothing is one
|
|
9
|
+
* nobody has ever put in front of them. Reading silence as a refusal there
|
|
10
|
+
* refuses an order over an account the customer has no page to go and turn on,
|
|
11
|
+
* which is an outage of our own making rather than a decision they made.
|
|
12
|
+
*
|
|
13
|
+
* So the gate turns on with the customer's first yes in that corridor, and from
|
|
14
|
+
* then on only the rails they have accepted can carry an order. A no on its own
|
|
15
|
+
* does not turn it on: it is reachable while the direction is opt-out, where a
|
|
16
|
+
* customer can switch off the rail they were seeded with and leave the rest
|
|
17
|
+
* merely unspoken about, and those customers would otherwise be blocked the
|
|
18
|
+
* moment the direction was switched over. Their no is still honoured either way,
|
|
19
|
+
* since a disabled rail is dropped from routing whatever this returns.
|
|
20
|
+
*
|
|
21
|
+
* Lives on its own so that routing, the pages that show a customer which accounts
|
|
22
|
+
* will take their orders, and the guard that stops them switching off their last
|
|
23
|
+
* usable account all answer it the same way. Those disagreeing is what makes a
|
|
24
|
+
* customer see every account switched off while their orders route perfectly well.
|
|
25
|
+
*/
|
|
26
|
+
export declare const isEnablementGateActive: ({ enablement, requireExplicitEnablement, }: {
|
|
27
|
+
enablement?: Pick<ProcessorEnablementState, "enabled"> | undefined;
|
|
28
|
+
requireExplicitEnablement?: boolean | undefined;
|
|
29
|
+
}) => boolean;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isEnablementGateActive = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Whether silence about a rail should be read as a refusal, for one customer in
|
|
6
|
+
* one corridor and one direction.
|
|
7
|
+
*
|
|
8
|
+
* The setting alone is not enough to answer it. Accounts are seeded and shown for
|
|
9
|
+
* the country a customer onboarded in, while an order or a quote may name any
|
|
10
|
+
* corridor we support, so a corridor where they have accepted nothing is one
|
|
11
|
+
* nobody has ever put in front of them. Reading silence as a refusal there
|
|
12
|
+
* refuses an order over an account the customer has no page to go and turn on,
|
|
13
|
+
* which is an outage of our own making rather than a decision they made.
|
|
14
|
+
*
|
|
15
|
+
* So the gate turns on with the customer's first yes in that corridor, and from
|
|
16
|
+
* then on only the rails they have accepted can carry an order. A no on its own
|
|
17
|
+
* does not turn it on: it is reachable while the direction is opt-out, where a
|
|
18
|
+
* customer can switch off the rail they were seeded with and leave the rest
|
|
19
|
+
* merely unspoken about, and those customers would otherwise be blocked the
|
|
20
|
+
* moment the direction was switched over. Their no is still honoured either way,
|
|
21
|
+
* since a disabled rail is dropped from routing whatever this returns.
|
|
22
|
+
*
|
|
23
|
+
* Lives on its own so that routing, the pages that show a customer which accounts
|
|
24
|
+
* will take their orders, and the guard that stops them switching off their last
|
|
25
|
+
* usable account all answer it the same way. Those disagreeing is what makes a
|
|
26
|
+
* customer see every account switched off while their orders route perfectly well.
|
|
27
|
+
*/
|
|
28
|
+
const isEnablementGateActive = ({ enablement, requireExplicitEnablement, }) => Boolean(requireExplicitEnablement && (enablement === null || enablement === void 0 ? void 0 : enablement.enabled.length));
|
|
29
|
+
exports.isEnablementGateActive = isEnablementGateActive;
|
|
@@ -17,6 +17,7 @@ const fintoc_deposit_CLABE_1 = require("../models/fintoc-deposit-CLABE");
|
|
|
17
17
|
const alfin_virtual_cci_1 = require("../models/alfin-virtual-cci");
|
|
18
18
|
const processor_readiness_1 = require("../models/processor-readiness");
|
|
19
19
|
const cluster_client_1 = require("../clients/cluster-client");
|
|
20
|
+
const enablement_gate_1 = require("./enablement-gate");
|
|
20
21
|
const processor_enablement_1 = require("./processor-enablement");
|
|
21
22
|
// Rails that give each user their own destination, which therefore has to exist
|
|
22
23
|
// before we can tell a customer where to pay. Every other rail is a shared house
|
|
@@ -300,12 +301,24 @@ const getPayinDestinations = ({ mongoose, user, country, fiat, processors, provi
|
|
|
300
301
|
.select({ processor: 1, status: 1, enablement: 1 })
|
|
301
302
|
.lean();
|
|
302
303
|
const readinessByProcessor = new Map(readiness.map((record) => [record.processor, record]));
|
|
304
|
+
// Read through the same gate routing uses, so a customer who has accepted nothing
|
|
305
|
+
// in this corridor is shown what will really happen - every account able to take
|
|
306
|
+
// an order - rather than every account switched off while their orders route fine.
|
|
307
|
+
const gateActive = (0, enablement_gate_1.isEnablementGateActive)({
|
|
308
|
+
enablement: {
|
|
309
|
+
enabled: processors.filter((processor) => {
|
|
310
|
+
var _a, _b, _c;
|
|
311
|
+
return ((_c = (_b = (_a = readinessByProcessor.get(processor)) === null || _a === void 0 ? void 0 : _a.enablement) === null || _b === void 0 ? void 0 : _b[common_1.Side.Buy]) === null || _c === void 0 ? void 0 : _c.isEnabled) === true;
|
|
312
|
+
}),
|
|
313
|
+
},
|
|
314
|
+
requireExplicitEnablement,
|
|
315
|
+
});
|
|
303
316
|
const isEnabled = (processor) => {
|
|
304
317
|
var _a;
|
|
305
318
|
return (0, processor_enablement_1.isProcessorEnabled)({
|
|
306
319
|
enablement: (_a = readinessByProcessor.get(processor)) === null || _a === void 0 ? void 0 : _a.enablement,
|
|
307
320
|
side: common_1.Side.Buy,
|
|
308
|
-
requireExplicitEnablement,
|
|
321
|
+
requireExplicitEnablement: gateActive,
|
|
309
322
|
});
|
|
310
323
|
};
|
|
311
324
|
const destinations = [];
|
|
@@ -12,6 +12,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
12
12
|
exports.ensureDefaultEnablement = exports.setProcessorEnablement = exports.getProcessorEnablementState = exports.isProcessorEnabled = void 0;
|
|
13
13
|
const common_1 = require("@riocrypto/common");
|
|
14
14
|
const processor_readiness_1 = require("../models/processor-readiness");
|
|
15
|
+
const enablement_gate_1 = require("./enablement-gate");
|
|
15
16
|
const get_processor_1 = require("./get-processor");
|
|
16
17
|
// Enablement is asked per side, so the purpose is fixed by the direction rather
|
|
17
18
|
// than chosen by the caller: verifications are ours to place and are never gated.
|
|
@@ -95,9 +96,18 @@ const setProcessorEnablement = ({ mongoose, userId, country, fiat, side, process
|
|
|
95
96
|
fiat,
|
|
96
97
|
side,
|
|
97
98
|
});
|
|
99
|
+
// Counts an unspoken rail as usable on exactly the terms routing does, which
|
|
100
|
+
// includes a customer who has accepted nothing here yet: their unspoken rails
|
|
101
|
+
// can still carry an order, so refusing to let them switch one off would be
|
|
102
|
+
// guarding a last usable account they do not have.
|
|
98
103
|
const stillUsable = [
|
|
99
104
|
...state.enabled,
|
|
100
|
-
...(
|
|
105
|
+
...((0, enablement_gate_1.isEnablementGateActive)({
|
|
106
|
+
enablement: state,
|
|
107
|
+
requireExplicitEnablement,
|
|
108
|
+
})
|
|
109
|
+
? []
|
|
110
|
+
: state.unset),
|
|
101
111
|
].filter((candidate) => candidate !== processor);
|
|
102
112
|
if (!stillUsable.length) {
|
|
103
113
|
throw new common_1.GenericInputError(side === common_1.Side.Buy
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.resolveProcessor = void 0;
|
|
4
4
|
const common_1 = require("@riocrypto/common");
|
|
5
|
+
const enablement_gate_1 = require("./enablement-gate");
|
|
5
6
|
const getRule = (config, country, fiat, purpose) => { var _a, _b; return (_b = (_a = config === null || config === void 0 ? void 0 : config[country]) === null || _a === void 0 ? void 0 : _a[fiat]) === null || _b === void 0 ? void 0 : _b[purpose]; };
|
|
6
7
|
// Renormalizes over the candidates it is given rather than assuming they still
|
|
7
8
|
// add up to 100, which is what lets a rail drop out - excluded by environment, or
|
|
@@ -29,9 +30,9 @@ const pickByShare = (candidates, position) => {
|
|
|
29
30
|
// corridor rather than from the rule. What keeps an order away from a rail is the
|
|
30
31
|
// customer, by switching it off or, while that direction is opt-in, by never
|
|
31
32
|
// turning it on. Two exceptions: a split set to apply to all users divides the
|
|
32
|
-
// corridor by percentage alone and asks nobody, and a corridor the customer
|
|
33
|
-
//
|
|
34
|
-
// there is not read as a refusal.
|
|
33
|
+
// corridor by percentage alone and asks nobody, and a corridor where the customer
|
|
34
|
+
// has accepted nothing yet is one they were never really asked about, so silence
|
|
35
|
+
// there is not read as a refusal either.
|
|
35
36
|
//
|
|
36
37
|
// Does no IO of its own - the routing config and the user's enablement are passed
|
|
37
38
|
// in - and the only nondeterminism is the per-order roll, which a caller can
|
|
@@ -120,21 +121,21 @@ const resolveProcessor = ({ country, fiat, purpose, routingConfig, excludedProce
|
|
|
120
121
|
const isGated = purpose !== common_1.ProcessorRoutingPurpose.BankAccountVerification;
|
|
121
122
|
const disabled = isGated ? (enablement === null || enablement === void 0 ? void 0 : enablement.disabled) || [] : [];
|
|
122
123
|
const unset = isGated && requireExplicitEnablement ? (enablement === null || enablement === void 0 ? void 0 : enablement.unset) || [] : [];
|
|
123
|
-
// Silence only means no in a corridor the customer has actually been asked
|
|
124
|
-
// about. Accounts are seeded and shown for the country they onboarded in, while
|
|
125
|
-
// a quote may name any corridor, so a corridor with nothing at all on record is
|
|
126
|
-
// one nobody has ever offered them rather than one they turned down. Refusing
|
|
127
|
-
// there would refuse a price over an account the customer has no page to go and
|
|
128
|
-
// turn on, so the gate stands down and the corridor routes as it did before
|
|
129
|
-
// opt-in. Anything they have answered, in either direction, puts the gate back.
|
|
130
|
-
const wasAsked = Boolean(enablement && (enablement.enabled.length || enablement.disabled.length));
|
|
131
124
|
// Recorded either way, and only acted on when the split leaves the choice with
|
|
132
125
|
// the customer. An order routed over their objection is the one that will be
|
|
133
126
|
// asked about later, so what they had said needs to survive on the decision.
|
|
134
127
|
const enablementOverridden = isGated && Boolean(rule === null || rule === void 0 ? void 0 : rule.appliesToAllUsers);
|
|
135
|
-
//
|
|
136
|
-
//
|
|
137
|
-
|
|
128
|
+
// Silence is only a refusal once the customer has told us what does work in this
|
|
129
|
+
// corridor - see isEnablementGateActive. Until then the rails they have not
|
|
130
|
+
// refused are all still in play, as they were before the direction went opt-in.
|
|
131
|
+
// The unspoken set is reported below either way, so a decision that routed past
|
|
132
|
+
// one can still be told from a decision that had none to route past.
|
|
133
|
+
const gatedUnset = (0, enablement_gate_1.isEnablementGateActive)({
|
|
134
|
+
enablement,
|
|
135
|
+
requireExplicitEnablement,
|
|
136
|
+
})
|
|
137
|
+
? unset
|
|
138
|
+
: [];
|
|
138
139
|
const candidates = enablementOverridden
|
|
139
140
|
? eligible
|
|
140
141
|
: eligible.filter((processor) => !disabled.includes(processor) && !gatedUnset.includes(processor));
|
package/build/index.d.ts
CHANGED
|
@@ -187,6 +187,7 @@ export * from "./helpers/resolve-processor";
|
|
|
187
187
|
export * from "./helpers/get-custom-rio-bank-account";
|
|
188
188
|
export * from "./helpers/payin-destinations";
|
|
189
189
|
export * from "./helpers/payin-verification";
|
|
190
|
+
export * from "./helpers/enablement-gate";
|
|
190
191
|
export * from "./helpers/processor-enablement";
|
|
191
192
|
export * from "./helpers/record-observed-processor-readiness";
|
|
192
193
|
export * from "./helpers/get-bulk-payment-from-reference";
|
package/build/index.js
CHANGED
|
@@ -203,6 +203,7 @@ __exportStar(require("./helpers/resolve-processor"), exports);
|
|
|
203
203
|
__exportStar(require("./helpers/get-custom-rio-bank-account"), exports);
|
|
204
204
|
__exportStar(require("./helpers/payin-destinations"), exports);
|
|
205
205
|
__exportStar(require("./helpers/payin-verification"), exports);
|
|
206
|
+
__exportStar(require("./helpers/enablement-gate"), exports);
|
|
206
207
|
__exportStar(require("./helpers/processor-enablement"), exports);
|
|
207
208
|
__exportStar(require("./helpers/record-observed-processor-readiness"), exports);
|
|
208
209
|
__exportStar(require("./helpers/get-bulk-payment-from-reference"), exports);
|