@riocrypto/common-server 1.0.2881 → 1.0.2882

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.
@@ -11,8 +11,18 @@ export interface PayinBankDetails {
11
11
  RFC?: string;
12
12
  bankAddress?: string;
13
13
  NIT?: string;
14
+ largeTransferCCI?: string;
14
15
  }
15
16
  export declare const PER_USER_PAYIN_PROCESSORS: Processor[];
17
+ /**
18
+ * Per-operation ceiling of the CCE's immediate transfer service, set by the BCRP.
19
+ *
20
+ * A virtual CCI accepts nothing but immediate transfers, so a payment above this
21
+ * cannot be sent to one at all: the payer's bank has to use deferred CCE or LBTR,
22
+ * and both are refused by a CCIV. Those payments go to the principal account
23
+ * instead, which is why the ceiling decides which CCI a customer is shown.
24
+ */
25
+ export declare const CCE_IMMEDIATE_CEILING_BY_FIAT: Partial<Record<Fiat, number>>;
16
26
  export declare const normalizeCci: (cci: string) => string;
17
27
  /**
18
28
  * Whether a CCI is one of Rio's own Peru accounts.
@@ -24,12 +34,14 @@ export declare const normalizeCci: (cci: string) => string;
24
34
  * order happened to be awaiting the same amount.
25
35
  */
26
36
  export declare const isRioOwnPeruAccountCci: (cci?: string) => boolean;
27
- export declare const getPayinBankDetails: ({ mongoose, processor, fiat, country, user, }: {
37
+ export declare const getPayinBankDetails: ({ mongoose, processor, fiat, country, user, amount, requireSharedAlfinAccount, }: {
28
38
  mongoose: Mongoose;
29
39
  processor: Processor;
30
40
  fiat: Fiat;
31
41
  country: Country;
32
42
  user: User;
43
+ amount?: number | undefined;
44
+ requireSharedAlfinAccount?: boolean | undefined;
33
45
  }) => Promise<PayinBankDetails>;
34
46
  export interface PayinDestination {
35
47
  processor: Processor;
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.getPayinDestinations = exports.getPayinBankDetails = exports.isRioOwnPeruAccountCci = exports.normalizeCci = exports.PER_USER_PAYIN_PROCESSORS = void 0;
12
+ exports.getPayinDestinations = exports.getPayinBankDetails = exports.isRioOwnPeruAccountCci = exports.normalizeCci = exports.CCE_IMMEDIATE_CEILING_BY_FIAT = exports.PER_USER_PAYIN_PROCESSORS = void 0;
13
13
  const common_1 = require("@riocrypto/common");
14
14
  const rio_bank_account_1 = require("../models/rio-bank-account");
15
15
  const STP_deposit_CLABE_1 = require("../models/STP-deposit-CLABE");
@@ -33,13 +33,32 @@ const PERU_COMPANY_ADDRESS = "Calle General de la Fuente, Edificio 393, dep. 102
33
33
  const PERU_RUC = "20610425713";
34
34
  // Rio's Alfin Cuenta Vista per currency. A CCIV is reachable only through the
35
35
  // interbank clearing house, so a customer who banks at Alfin cannot pay one from
36
- // inside Alfin and needs the underlying account number. Note that a payment sent
37
- // here carries no CCIV, so Alfin raises no payin notification for it: it is only
38
- // picked up by the treasury statement import and has to be matched by hand.
36
+ // inside Alfin and needs the underlying account number. A payment sent here
37
+ // carries no CCIV, so Alfin raises no payin notification for it: it is picked up
38
+ // by the treasury statement import and attributed from there.
39
39
  const ALFIN_ACCOUNT_NUMBER_BY_FIAT = {
40
40
  [common_1.Fiat.PEN]: "01818233900001",
41
41
  [common_1.Fiat.USD]: "01818233900002",
42
42
  };
43
+ // The same accounts as CCIs, for payers at another bank. An account number is
44
+ // only addressable from inside Alfin, so this is what a customer needs when the
45
+ // payment cannot go to their CCIV.
46
+ const ALFIN_PRINCIPAL_CCI_BY_FIAT = {
47
+ [common_1.Fiat.PEN]: "05810001818233900196",
48
+ [common_1.Fiat.USD]: "05810001818233900294",
49
+ };
50
+ /**
51
+ * Per-operation ceiling of the CCE's immediate transfer service, set by the BCRP.
52
+ *
53
+ * A virtual CCI accepts nothing but immediate transfers, so a payment above this
54
+ * cannot be sent to one at all: the payer's bank has to use deferred CCE or LBTR,
55
+ * and both are refused by a CCIV. Those payments go to the principal account
56
+ * instead, which is why the ceiling decides which CCI a customer is shown.
57
+ */
58
+ exports.CCE_IMMEDIATE_CEILING_BY_FIAT = {
59
+ [common_1.Fiat.PEN]: 30000,
60
+ [common_1.Fiat.USD]: 10000,
61
+ };
43
62
  const INTERBANK_PERU_CCI_BY_FIAT = {
44
63
  [common_1.Fiat.PEN]: "003-200-003004741070-36",
45
64
  [common_1.Fiat.USD]: "003-200-003004741088-38",
@@ -144,8 +163,10 @@ const getStaticPayinBankDetails = (processor, fiat) => {
144
163
  // Looks up (and by default creates) the user's own destination on a per-user
145
164
  // rail. With `provision` false it reports what exists without calling out to the
146
165
  // provider, which is what the whitelisting list needs so that merely viewing the
147
- // page does not allocate account numbers at Fintoc or Alfin.
148
- const getPerUserPayinBankDetails = ({ mongoose, processor, fiat, userId, provision, }) => __awaiter(void 0, void 0, void 0, function* () {
166
+ // page does not allocate account numbers at Fintoc or Alfin. `amount` is the sum
167
+ // the customer will send in one transfer, which on Alfin decides whether their
168
+ // virtual CCI can receive it at all.
169
+ const getPerUserPayinBankDetails = ({ mongoose, processor, fiat, userId, provision, amount, requireSharedAlfinAccount, }) => __awaiter(void 0, void 0, void 0, function* () {
149
170
  if (processor === common_1.Processor.SPEI_STP) {
150
171
  const STPDepositCLABE = (0, STP_deposit_CLABE_1.buildSTPDepositCLABE)(mongoose);
151
172
  const existing = yield STPDepositCLABE.findOne({ userId });
@@ -191,22 +212,34 @@ const getPerUserPayinBankDetails = ({ mongoose, processor, fiat, userId, provisi
191
212
  };
192
213
  }
193
214
  if (processor === common_1.Processor.Alfin) {
194
- const AlfinVirtualCci = (0, alfin_virtual_cci_1.buildAlfinVirtualCci)(mongoose);
195
- const existing = yield AlfinVirtualCci.findOne({ userId, fiat });
196
- let CCIV = existing === null || existing === void 0 ? void 0 : existing.CCIV;
197
- if (!CCIV) {
198
- if (!provision) {
199
- return undefined;
215
+ // Above the immediate-transfer ceiling the customer is given the principal
216
+ // account's CCI rather than their own virtual one. Showing the CCIV there
217
+ // would be showing them the one destination their bank cannot pay: the
218
+ // transfer has to go out on a rail a CCIV refuses, so it would never arrive.
219
+ const ceiling = exports.CCE_IMMEDIATE_CEILING_BY_FIAT[fiat];
220
+ const exceedsCcivCeiling = amount !== undefined && ceiling !== undefined && amount > ceiling;
221
+ const usePrincipalAccount = Boolean(requireSharedAlfinAccount) || exceedsCcivCeiling;
222
+ let CCI = usePrincipalAccount
223
+ ? ALFIN_PRINCIPAL_CCI_BY_FIAT[fiat]
224
+ : undefined;
225
+ if (!usePrincipalAccount) {
226
+ const AlfinVirtualCci = (0, alfin_virtual_cci_1.buildAlfinVirtualCci)(mongoose);
227
+ const existing = yield AlfinVirtualCci.findOne({ userId, fiat });
228
+ CCI = existing === null || existing === void 0 ? void 0 : existing.CCIV;
229
+ if (!CCI) {
230
+ if (!provision) {
231
+ return undefined;
232
+ }
233
+ const clusterClient = yield (0, cluster_client_1.buildClusterClient)();
234
+ CCI = (yield clusterClient.generateAlfinVirtualCci(userId, fiat)).CCIV;
200
235
  }
201
- const clusterClient = yield (0, cluster_client_1.buildClusterClient)();
202
- CCIV = (yield clusterClient.generateAlfinVirtualCci(userId, fiat)).CCIV;
203
236
  }
204
237
  return {
205
238
  bankName: "Alfin Banco",
206
239
  companyName: PERU_COMPANY_NAME,
207
240
  companyAddress: PERU_COMPANY_ADDRESS,
208
241
  accountNumber: ALFIN_ACCOUNT_NUMBER_BY_FIAT[fiat],
209
- CCI: CCIV,
242
+ CCI,
210
243
  RUC: PERU_RUC,
211
244
  };
212
245
  }
@@ -215,7 +248,7 @@ const getPerUserPayinBankDetails = ({ mongoose, processor, fiat, userId, provisi
215
248
  // The account a customer must pay into to fund a buy order on a given rail.
216
249
  // A custom Rio bank account replaces the rail's own destination outright, which
217
250
  // is why routing has to know that account's processor - see resolveProcessor.
218
- const getPayinBankDetails = ({ mongoose, processor, fiat, country, user, }) => __awaiter(void 0, void 0, void 0, function* () {
251
+ const getPayinBankDetails = ({ mongoose, processor, fiat, country, user, amount, requireSharedAlfinAccount, }) => __awaiter(void 0, void 0, void 0, function* () {
219
252
  var _a, _b, _c;
220
253
  const rioBankAccountId = (_c = (_b = (_a = user.rioBankAccount) === null || _a === void 0 ? void 0 : _a[country]) === null || _b === void 0 ? void 0 : _b[fiat]) === null || _c === void 0 ? void 0 : _c.id;
221
254
  if (rioBankAccountId) {
@@ -243,6 +276,8 @@ const getPayinBankDetails = ({ mongoose, processor, fiat, country, user, }) => _
243
276
  fiat,
244
277
  userId: user.id,
245
278
  provision: true,
279
+ amount,
280
+ requireSharedAlfinAccount,
246
281
  });
247
282
  return details || {};
248
283
  }
@@ -280,6 +315,12 @@ const getPayinDestinations = ({ mongoose, user, country, fiat, processors, provi
280
315
  userId: user.id,
281
316
  provision,
282
317
  });
318
+ // A customer who may only send to accounts their bank has on file has to
319
+ // have both Alfin CCIs on it before they place an order, since which one
320
+ // they are given depends on how much that order is for.
321
+ if (processor === common_1.Processor.Alfin && bankDetails) {
322
+ bankDetails.largeTransferCCI = ALFIN_PRINCIPAL_CCI_BY_FIAT[fiat];
323
+ }
283
324
  }
284
325
  else {
285
326
  bankDetails = getStaticPayinBankDetails(processor, fiat);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@riocrypto/common-server",
3
- "version": "1.0.2881",
3
+ "version": "1.0.2882",
4
4
  "description": "",
5
5
  "main": "./build/index.js",
6
6
  "types": "./build/index.d.ts",