@riocrypto/common-server 1.0.2881 → 1.0.2883
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.
|
@@ -33,6 +33,13 @@ export interface KrakenWithdrawInfo {
|
|
|
33
33
|
amount: string;
|
|
34
34
|
fee: string;
|
|
35
35
|
}
|
|
36
|
+
export interface KrakenFundingQuery {
|
|
37
|
+
method?: string;
|
|
38
|
+
start?: number;
|
|
39
|
+
end?: number;
|
|
40
|
+
maxPages?: number;
|
|
41
|
+
stopWhen?: (row: KrakenFundingStatus) => boolean;
|
|
42
|
+
}
|
|
36
43
|
export interface KrakenLedgerEntry {
|
|
37
44
|
refid: string;
|
|
38
45
|
time: number;
|
|
@@ -62,16 +69,19 @@ declare class KrakenClient {
|
|
|
62
69
|
getAllBalances(assets: string[]): Promise<Record<string, number>>;
|
|
63
70
|
getDepositMethods(asset: string): Promise<KrakenDepositMethod[]>;
|
|
64
71
|
getDepositAddresses(asset: string, method: string, isNew?: boolean): Promise<KrakenDepositAddress[]>;
|
|
65
|
-
|
|
72
|
+
private listFunding;
|
|
73
|
+
getDepositStatus(asset: string, query?: KrakenFundingQuery): Promise<KrakenFundingStatus[]>;
|
|
66
74
|
getWithdrawInfo(asset: string, key: string, amount: number): Promise<KrakenWithdrawInfo>;
|
|
67
75
|
withdraw(asset: string, key: string, amount: number): Promise<string>;
|
|
68
|
-
getWithdrawStatus(asset: string,
|
|
76
|
+
getWithdrawStatus(asset: string, query?: KrakenFundingQuery): Promise<KrakenFundingStatus[]>;
|
|
69
77
|
getWithdrawStatusByRefid(asset: string, refid: string): Promise<KrakenFundingStatus | undefined>;
|
|
70
78
|
getDepositByTxId(asset: string, txid: string): Promise<KrakenFundingStatus | undefined>;
|
|
71
79
|
getLedgers(params?: {
|
|
72
80
|
type?: string;
|
|
73
81
|
asset?: string;
|
|
74
82
|
start?: number;
|
|
83
|
+
end?: number;
|
|
84
|
+
maxPages?: number;
|
|
75
85
|
}): Promise<Record<string, KrakenLedgerEntry>>;
|
|
76
86
|
}
|
|
77
87
|
export declare const buildKrakenClient: () => Promise<KrakenClient>;
|
|
@@ -28,6 +28,42 @@ const getKrakenRestBaseUrl = (env) => env === common_1.RioEnv.Production
|
|
|
28
28
|
: KRAKEN_UAT_REST_BASE_URL;
|
|
29
29
|
// Kraken Balance keys. Fiat USD is `ZUSD`; the stablecoins use their ticker.
|
|
30
30
|
exports.KRAKEN_ASSET_USD = "ZUSD";
|
|
31
|
+
// Page size we ask the funding endpoints for. Their own defaults differ sharply
|
|
32
|
+
// - DepositStatus returns 25 rows and WithdrawStatus 500 - so always send an
|
|
33
|
+
// explicit limit rather than inheriting whichever default applies. Reading only
|
|
34
|
+
// the first default-size page is what previously made older deposits invisible.
|
|
35
|
+
const FUNDING_PAGE_LIMIT = 500;
|
|
36
|
+
// Ledgers returns 50 rows per call and pages via a numeric `ofs` offset.
|
|
37
|
+
const LEDGER_PAGE_SIZE = 50;
|
|
38
|
+
// Ceiling on pages any single call will walk. The private-request queue
|
|
39
|
+
// serializes these, so an unbounded walk would both stall the queue and burn
|
|
40
|
+
// the per-account rate counter that liquidity-management and external-trading
|
|
41
|
+
// share.
|
|
42
|
+
const MAX_FUNDING_PAGES = 40;
|
|
43
|
+
const MAX_LEDGER_PAGES = 40;
|
|
44
|
+
// The funding endpoints answer either with a bare array (when `cursor` is
|
|
45
|
+
// disabled) or with an object holding the rows plus `next_cursor`. That
|
|
46
|
+
// object's row property is documented as `deposit` for DepositStatus and is not
|
|
47
|
+
// documented at all for WithdrawStatus, so take the first array-valued property
|
|
48
|
+
// instead of trusting a name: guessing the key wrong yields a silent zero rows
|
|
49
|
+
// rather than an error.
|
|
50
|
+
const normalizeFundingPage = (raw) => {
|
|
51
|
+
var _a;
|
|
52
|
+
if (Array.isArray(raw)) {
|
|
53
|
+
return { rows: raw };
|
|
54
|
+
}
|
|
55
|
+
if (!raw || typeof raw !== "object") {
|
|
56
|
+
return { rows: [] };
|
|
57
|
+
}
|
|
58
|
+
const record = raw;
|
|
59
|
+
const rows = (_a = Object.values(record).find((value) => Array.isArray(value))) !== null && _a !== void 0 ? _a : [];
|
|
60
|
+
const nextCursor = typeof record.next_cursor === "string" ? record.next_cursor : undefined;
|
|
61
|
+
return { rows, nextCursor };
|
|
62
|
+
};
|
|
63
|
+
// Cursor pages restart from the newest record, so the same row can appear on
|
|
64
|
+
// more than one page. Identity is the funding reference plus its transaction
|
|
65
|
+
// and timestamp.
|
|
66
|
+
const fundingRowKey = (row) => `${row.refid}:${row.txid}:${row.time}`;
|
|
31
67
|
class KrakenClient {
|
|
32
68
|
constructor(apiKey, apiSecret, env) {
|
|
33
69
|
this.apiKey = apiKey;
|
|
@@ -146,12 +182,51 @@ class KrakenClient {
|
|
|
146
182
|
});
|
|
147
183
|
});
|
|
148
184
|
}
|
|
149
|
-
|
|
185
|
+
// Walk a funding endpoint to exhaustion (or to `maxPages`). The first call
|
|
186
|
+
// deliberately omits `cursor` so it matches the documented unpaginated form;
|
|
187
|
+
// pagination is enabled from the second call onward, which restarts at the
|
|
188
|
+
// newest record and so overlaps the first page. Duplicates are dropped by
|
|
189
|
+
// reference id, making the overlap harmless.
|
|
190
|
+
listFunding(endpoint, asset, query) {
|
|
191
|
+
var _a;
|
|
150
192
|
return __awaiter(this, void 0, void 0, function* () {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
193
|
+
const maxPages = (_a = query.maxPages) !== null && _a !== void 0 ? _a : MAX_FUNDING_PAGES;
|
|
194
|
+
const rows = [];
|
|
195
|
+
const seen = new Set();
|
|
196
|
+
let cursor;
|
|
197
|
+
for (let page = 0; page < maxPages; page++) {
|
|
198
|
+
const raw = yield this.privatePost(endpoint, {
|
|
199
|
+
asset,
|
|
200
|
+
method: query.method,
|
|
201
|
+
start: query.start,
|
|
202
|
+
end: query.end,
|
|
203
|
+
limit: FUNDING_PAGE_LIMIT,
|
|
204
|
+
cursor: page === 0 ? undefined : cursor !== null && cursor !== void 0 ? cursor : true,
|
|
205
|
+
});
|
|
206
|
+
const { rows: batch, nextCursor } = normalizeFundingPage(raw);
|
|
207
|
+
for (const row of batch) {
|
|
208
|
+
const key = fundingRowKey(row);
|
|
209
|
+
if (!seen.has(key)) {
|
|
210
|
+
seen.add(key);
|
|
211
|
+
rows.push(row);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
if (query.stopWhen && batch.some(query.stopWhen)) {
|
|
215
|
+
break;
|
|
216
|
+
}
|
|
217
|
+
// Page 0 carries no cursor, so allow one more call to obtain one; after
|
|
218
|
+
// that, no cursor means there is nothing further back.
|
|
219
|
+
if (batch.length === 0 || (page > 0 && !nextCursor)) {
|
|
220
|
+
break;
|
|
221
|
+
}
|
|
222
|
+
cursor = nextCursor;
|
|
223
|
+
}
|
|
224
|
+
return rows;
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
getDepositStatus(asset, query = {}) {
|
|
228
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
229
|
+
return this.listFunding("DepositStatus", asset, query);
|
|
155
230
|
});
|
|
156
231
|
}
|
|
157
232
|
// ----- Withdrawals -----
|
|
@@ -181,41 +256,64 @@ class KrakenClient {
|
|
|
181
256
|
return result.refid;
|
|
182
257
|
});
|
|
183
258
|
}
|
|
184
|
-
getWithdrawStatus(asset,
|
|
259
|
+
getWithdrawStatus(asset, query = {}) {
|
|
185
260
|
return __awaiter(this, void 0, void 0, function* () {
|
|
186
|
-
return this.
|
|
187
|
-
asset,
|
|
188
|
-
method,
|
|
189
|
-
});
|
|
261
|
+
return this.listFunding("WithdrawStatus", asset, query);
|
|
190
262
|
});
|
|
191
263
|
}
|
|
192
264
|
getWithdrawStatusByRefid(asset, refid) {
|
|
193
265
|
return __awaiter(this, void 0, void 0, function* () {
|
|
194
|
-
const statuses = yield this.getWithdrawStatus(asset
|
|
266
|
+
const statuses = yield this.getWithdrawStatus(asset, {
|
|
267
|
+
stopWhen: (row) => row.refid === refid,
|
|
268
|
+
});
|
|
195
269
|
return statuses.find((s) => s.refid === refid);
|
|
196
270
|
});
|
|
197
271
|
}
|
|
198
272
|
getDepositByTxId(asset, txid) {
|
|
199
273
|
return __awaiter(this, void 0, void 0, function* () {
|
|
200
|
-
const statuses = yield this.getDepositStatus(asset
|
|
274
|
+
const statuses = yield this.getDepositStatus(asset, {
|
|
275
|
+
stopWhen: (row) => row.txid === txid,
|
|
276
|
+
});
|
|
201
277
|
return statuses.find((s) => s.txid === txid);
|
|
202
278
|
});
|
|
203
279
|
}
|
|
204
280
|
// ----- Ledgers -----
|
|
205
|
-
// Returns the ledger entries (keyed by ledger id) for the given filters
|
|
206
|
-
//
|
|
207
|
-
//
|
|
208
|
-
//
|
|
209
|
-
//
|
|
281
|
+
// Returns the ledger entries (keyed by ledger id) for the given filters,
|
|
282
|
+
// walking every page rather than just the most recent 50. Kraken caps a
|
|
283
|
+
// response at 50 rows and reports the full match count, so pagination is via
|
|
284
|
+
// the numeric `ofs` offset until that count is covered. `start`/`end` are
|
|
285
|
+
// unix timestamps in seconds.
|
|
210
286
|
getLedgers(params = {}) {
|
|
211
|
-
var _a;
|
|
287
|
+
var _a, _b, _c;
|
|
212
288
|
return __awaiter(this, void 0, void 0, function* () {
|
|
213
|
-
const
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
289
|
+
const maxPages = (_a = params.maxPages) !== null && _a !== void 0 ? _a : MAX_LEDGER_PAGES;
|
|
290
|
+
const merged = {};
|
|
291
|
+
for (let page = 0; page < maxPages; page++) {
|
|
292
|
+
const result = yield this.privatePost("Ledgers", {
|
|
293
|
+
type: params.type,
|
|
294
|
+
asset: params.asset,
|
|
295
|
+
start: params.start,
|
|
296
|
+
end: params.end,
|
|
297
|
+
ofs: page * LEDGER_PAGE_SIZE,
|
|
298
|
+
});
|
|
299
|
+
const rows = (_b = result === null || result === void 0 ? void 0 : result.ledger) !== null && _b !== void 0 ? _b : {};
|
|
300
|
+
const pageSize = Object.keys(rows).length;
|
|
301
|
+
if (pageSize === 0) {
|
|
302
|
+
break;
|
|
303
|
+
}
|
|
304
|
+
Object.assign(merged, rows);
|
|
305
|
+
// A short page is the last one. `count` is Kraken's total for the filter;
|
|
306
|
+
// it is only trusted when present so a missing count cannot terminate the
|
|
307
|
+
// walk after a single page.
|
|
308
|
+
if (pageSize < LEDGER_PAGE_SIZE) {
|
|
309
|
+
break;
|
|
310
|
+
}
|
|
311
|
+
const count = (_c = result === null || result === void 0 ? void 0 : result.count) !== null && _c !== void 0 ? _c : 0;
|
|
312
|
+
if (count > 0 && Object.keys(merged).length >= count) {
|
|
313
|
+
break;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
return merged;
|
|
219
317
|
});
|
|
220
318
|
}
|
|
221
319
|
}
|
|
@@ -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.
|
|
37
|
-
//
|
|
38
|
-
//
|
|
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
|
-
|
|
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
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
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
|
|
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);
|