@riocrypto/common-server 1.0.2878 → 1.0.2879
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/clients/cluster-client.d.ts +36 -0
- package/build/clients/cluster-client.js +31 -1
- package/build/helpers/get-custom-rio-bank-account.d.ts +10 -0
- package/build/helpers/get-custom-rio-bank-account.js +37 -0
- package/build/helpers/get-processor.d.ts +7 -4
- package/build/helpers/get-processor.js +72 -55
- package/build/helpers/get-tax-rate.js +1 -0
- package/build/helpers/payin-destinations.d.ts +37 -0
- package/build/helpers/payin-destinations.js +286 -0
- package/build/helpers/payin-verification.d.ts +30 -0
- package/build/helpers/payin-verification.js +162 -0
- package/build/helpers/processor-enablement.d.ts +19 -0
- package/build/helpers/processor-enablement.js +87 -0
- package/build/helpers/record-observed-processor-readiness.d.ts +10 -0
- package/build/helpers/record-observed-processor-readiness.js +65 -0
- package/build/helpers/resolve-processor.d.ts +18 -0
- package/build/helpers/resolve-processor.js +122 -0
- package/build/index.d.ts +10 -0
- package/build/index.js +10 -0
- package/build/middlewares/get-order.js +1 -0
- package/build/models/bank-account-verification.d.ts +2 -2
- package/build/models/bulk-bank-payment.js +3 -0
- package/build/models/fintoc-deposit-CLABE.d.ts +28 -0
- package/build/models/fintoc-deposit-CLABE.js +56 -0
- package/build/models/fintoc-mxn-withdrawal.d.ts +51 -0
- package/build/models/fintoc-mxn-withdrawal.js +88 -0
- package/build/models/fireblocks-vault.d.ts +8 -0
- package/build/models/fireblocks-vault.js +8 -0
- package/build/models/internal-balances.d.ts +3 -0
- package/build/models/internal-balances.js +3 -0
- package/build/models/payment-address-verification.d.ts +49 -0
- package/build/models/payment-address-verification.js +77 -0
- package/build/models/processor-readiness.d.ts +44 -0
- package/build/models/processor-readiness.js +90 -0
- package/build/models/rio-bank-account.d.ts +3 -1
- package/build/models/rio-bank-account.js +3 -0
- package/build/models/rio-settings.d.ts +3 -11
- package/build/models/rio-settings.js +1 -2
- package/package.json +2 -2
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Country, Fiat, Processor, ProcessorRoutingConfig, ProcessorRoutingPurpose } from "@riocrypto/common";
|
|
2
|
+
export interface ResolveProcessorParams {
|
|
3
|
+
country: Country;
|
|
4
|
+
fiat: Fiat;
|
|
5
|
+
purpose: ProcessorRoutingPurpose;
|
|
6
|
+
routingConfig?: ProcessorRoutingConfig;
|
|
7
|
+
excludedProcessors?: Processor[];
|
|
8
|
+
disabledProcessors?: Processor[];
|
|
9
|
+
customRioBankAccount?: {
|
|
10
|
+
processor?: Processor;
|
|
11
|
+
};
|
|
12
|
+
randomSeed?: number;
|
|
13
|
+
}
|
|
14
|
+
export interface ResolveProcessorResult {
|
|
15
|
+
processor?: Processor;
|
|
16
|
+
reason: "customRioBankAccount" | "customRioBankAccountWithoutRail" | "split" | "onlyCandidate" | "enabledRailWithoutShare" | "noRuleConfigured" | "noEligibleCandidate" | "noEnabledCandidate";
|
|
17
|
+
}
|
|
18
|
+
export declare const resolveProcessor: ({ country, fiat, purpose, routingConfig, excludedProcessors, disabledProcessors, customRioBankAccount, randomSeed, }: ResolveProcessorParams) => ResolveProcessorResult;
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveProcessor = void 0;
|
|
4
|
+
const common_1 = require("@riocrypto/common");
|
|
5
|
+
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
|
+
// Renormalizes over the candidates it is given rather than assuming they still
|
|
7
|
+
// add up to 100, which is what lets a rail drop out - excluded by environment, or
|
|
8
|
+
// switched off by the customer - and have its share absorbed proportionally by
|
|
9
|
+
// the rest.
|
|
10
|
+
const pickByShare = (candidates, position) => {
|
|
11
|
+
const total = candidates.reduce((acc, c) => acc + c.percentage, 0);
|
|
12
|
+
let cursor = position * total;
|
|
13
|
+
for (const candidate of candidates) {
|
|
14
|
+
cursor -= candidate.percentage;
|
|
15
|
+
if (cursor < 0) {
|
|
16
|
+
return candidate.processor;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
// Floating point can leave the cursor a hair above zero on the last step.
|
|
20
|
+
return candidates[candidates.length - 1].processor;
|
|
21
|
+
};
|
|
22
|
+
// Chooses the payment processor for a buy, a sell or a bank account verification
|
|
23
|
+
// from the configured split.
|
|
24
|
+
//
|
|
25
|
+
// A percentage divides volume between the rails that are actually available to
|
|
26
|
+
// the customer; it is not a switch. A rail left at zero, or left out of the rule
|
|
27
|
+
// altogether, still takes their orders when it is the only one they have left
|
|
28
|
+
// enabled, which is why the candidate set comes from the corridor rather than
|
|
29
|
+
// from the rule. Switching a rail off is the only way to keep an order away from
|
|
30
|
+
// it.
|
|
31
|
+
//
|
|
32
|
+
// Does no IO of its own - the routing config and the user's readiness are passed
|
|
33
|
+
// in - and the only nondeterminism is the per-order roll, which a caller can
|
|
34
|
+
// pin down by supplying randomSeed. Because the roll happens once, the answer
|
|
35
|
+
// belongs to the record that stores it: anything that needs to know which rail
|
|
36
|
+
// an existing order uses reads it off the order rather than calling again.
|
|
37
|
+
//
|
|
38
|
+
// Only handles rails that participate in a split. Structural routing that is not
|
|
39
|
+
// a commercial choice - Binance RFQ, COP, USD in the US or Mexico - stays in
|
|
40
|
+
// getProcessor and never reaches here.
|
|
41
|
+
const resolveProcessor = ({ country, fiat, purpose, routingConfig, excludedProcessors, disabledProcessors, customRioBankAccount, randomSeed, }) => {
|
|
42
|
+
const isEligible = (processor) => !(excludedProcessors === null || excludedProcessors === void 0 ? void 0 : excludedProcessors.includes(processor));
|
|
43
|
+
// A rail the customer has switched off for this direction is worthless whatever
|
|
44
|
+
// share it carries: on a buy they cannot send money to it, on a sell their bank
|
|
45
|
+
// will not accept the credit. Applies to every rail, verifiable or not - a bank
|
|
46
|
+
// can refuse a wire from Bancrea as easily as a SPEI transfer from Fintoc.
|
|
47
|
+
//
|
|
48
|
+
// Verifications are exempt because they are ours to place against an account the
|
|
49
|
+
// customer gave us, not a rail they have to accept.
|
|
50
|
+
const isUsable = (processor) => purpose === common_1.ProcessorRoutingPurpose.BankAccountVerification ||
|
|
51
|
+
!(disabledProcessors === null || disabledProcessors === void 0 ? void 0 : disabledProcessors.includes(processor));
|
|
52
|
+
// A custom Rio bank account outranks everything on buys, because it is where
|
|
53
|
+
// the money physically goes: `getBankDetails` returns it in place of the
|
|
54
|
+
// rail's own destination. Routing the order to a different processor would
|
|
55
|
+
// leave the order's processor and the account the payin lands in disagreeing,
|
|
56
|
+
// which breaks deposit matching, payout retry and the readiness gate at once.
|
|
57
|
+
// Sells and verifications never touch it - both are outbound.
|
|
58
|
+
if (customRioBankAccount && purpose === common_1.ProcessorRoutingPurpose.Buy) {
|
|
59
|
+
const { processor } = customRioBankAccount;
|
|
60
|
+
// Accounts predating the processor field have an unknown rail. Guessing
|
|
61
|
+
// would reintroduce the very mismatch this is here to prevent, so hand back
|
|
62
|
+
// to the structural path and leave these users exactly as they were until an
|
|
63
|
+
// admin records which rail the account belongs to.
|
|
64
|
+
if (!processor) {
|
|
65
|
+
return { reason: "customRioBankAccountWithoutRail" };
|
|
66
|
+
}
|
|
67
|
+
// Deliberately fail closed rather than fall through to the split. The payin
|
|
68
|
+
// destination is fixed, so if that rail cannot be used here the only honest
|
|
69
|
+
// options are to refuse the order or to keep sending payins to a provider we
|
|
70
|
+
// have stopped watching.
|
|
71
|
+
if (!isEligible(processor)) {
|
|
72
|
+
return { reason: "noEligibleCandidate" };
|
|
73
|
+
}
|
|
74
|
+
return { processor, reason: "customRioBankAccount" };
|
|
75
|
+
}
|
|
76
|
+
const rule = getRule(routingConfig, country, fiat, purpose);
|
|
77
|
+
if (!rule) {
|
|
78
|
+
return { reason: "noRuleConfigured" };
|
|
79
|
+
}
|
|
80
|
+
// Starts from the corridor's rails rather than from the rails the rule names,
|
|
81
|
+
// because a percentage decides how volume is divided between the rails a
|
|
82
|
+
// customer can use - it is not what makes a rail usable. Also drops any share
|
|
83
|
+
// stored against a rail this purpose does not serve, which nothing dispatches.
|
|
84
|
+
const corridorProcessors = (0, common_1.getProcessorsForCorridor)(country, fiat, purpose);
|
|
85
|
+
const eligible = corridorProcessors.filter(isEligible);
|
|
86
|
+
if (!eligible.length) {
|
|
87
|
+
return { reason: "noEligibleCandidate" };
|
|
88
|
+
}
|
|
89
|
+
const candidates = eligible.filter(isUsable);
|
|
90
|
+
if (!candidates.length) {
|
|
91
|
+
return { reason: "noEnabledCandidate" };
|
|
92
|
+
}
|
|
93
|
+
const shares = candidates
|
|
94
|
+
.map((processor) => ({
|
|
95
|
+
processor,
|
|
96
|
+
percentage: Number(rule.percentages[processor]) || 0,
|
|
97
|
+
}))
|
|
98
|
+
.filter((candidate) => candidate.percentage > 0);
|
|
99
|
+
// None of the rails this customer can use carries a share, so there is no split
|
|
100
|
+
// to draw from. Refusing the order would read a zero as "never use this rail",
|
|
101
|
+
// when all it says is where volume goes while there is somewhere else to send
|
|
102
|
+
// it. Prefers the corridor default and otherwise the corridor's own order, so
|
|
103
|
+
// the rail a customer in this position gets is predictable rather than rolled.
|
|
104
|
+
if (!shares.length) {
|
|
105
|
+
const fallback = (0, common_1.getDefaultProcessor)(country, fiat, purpose, excludedProcessors);
|
|
106
|
+
return {
|
|
107
|
+
processor: fallback && candidates.includes(fallback) ? fallback : candidates[0],
|
|
108
|
+
reason: "enabledRailWithoutShare",
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
if (shares.length === 1) {
|
|
112
|
+
return { processor: shares[0].processor, reason: "onlyCandidate" };
|
|
113
|
+
}
|
|
114
|
+
// Rolled per order, so the realized share converges on the configured
|
|
115
|
+
// percentages by order count. Nothing is persisted here: a caller that needs
|
|
116
|
+
// the same answer twice passes back the seed it used.
|
|
117
|
+
return {
|
|
118
|
+
processor: pickByShare(shares, randomSeed !== null && randomSeed !== void 0 ? randomSeed : Math.random()),
|
|
119
|
+
reason: "split",
|
|
120
|
+
};
|
|
121
|
+
};
|
|
122
|
+
exports.resolveProcessor = resolveProcessor;
|
package/build/index.d.ts
CHANGED
|
@@ -87,6 +87,10 @@ export * from "./models/admin-auth-dashboard-settings";
|
|
|
87
87
|
export * from "./models/STP-mxn-withdrawal";
|
|
88
88
|
export * from "./models/STP-deposit-CLABE";
|
|
89
89
|
export * from "./models/STP-settings";
|
|
90
|
+
export * from "./models/fintoc-mxn-withdrawal";
|
|
91
|
+
export * from "./models/fintoc-deposit-CLABE";
|
|
92
|
+
export * from "./models/processor-readiness";
|
|
93
|
+
export * from "./models/payment-address-verification";
|
|
90
94
|
export * from "./models/alfin-virtual-cci";
|
|
91
95
|
export * from "./models/alfin-settings";
|
|
92
96
|
export * from "./models/alfin-withdrawal";
|
|
@@ -175,6 +179,12 @@ export * from "./helpers/generate-idempotency-key-from-order";
|
|
|
175
179
|
export * from "./helpers/generate-idempotency-key-from-bulk-payout";
|
|
176
180
|
export * from "./helpers/get-is-fireblocks-signature-valid";
|
|
177
181
|
export * from "./helpers/get-processor";
|
|
182
|
+
export * from "./helpers/resolve-processor";
|
|
183
|
+
export * from "./helpers/get-custom-rio-bank-account";
|
|
184
|
+
export * from "./helpers/payin-destinations";
|
|
185
|
+
export * from "./helpers/payin-verification";
|
|
186
|
+
export * from "./helpers/processor-enablement";
|
|
187
|
+
export * from "./helpers/record-observed-processor-readiness";
|
|
178
188
|
export * from "./helpers/get-bulk-payment-from-reference";
|
|
179
189
|
export * from "./helpers/extract-error-message";
|
|
180
190
|
export * from "./helpers/get-exchange-rates-with-markups";
|
package/build/index.js
CHANGED
|
@@ -103,6 +103,10 @@ __exportStar(require("./models/admin-auth-dashboard-settings"), exports);
|
|
|
103
103
|
__exportStar(require("./models/STP-mxn-withdrawal"), exports);
|
|
104
104
|
__exportStar(require("./models/STP-deposit-CLABE"), exports);
|
|
105
105
|
__exportStar(require("./models/STP-settings"), exports);
|
|
106
|
+
__exportStar(require("./models/fintoc-mxn-withdrawal"), exports);
|
|
107
|
+
__exportStar(require("./models/fintoc-deposit-CLABE"), exports);
|
|
108
|
+
__exportStar(require("./models/processor-readiness"), exports);
|
|
109
|
+
__exportStar(require("./models/payment-address-verification"), exports);
|
|
106
110
|
__exportStar(require("./models/alfin-virtual-cci"), exports);
|
|
107
111
|
__exportStar(require("./models/alfin-settings"), exports);
|
|
108
112
|
__exportStar(require("./models/alfin-withdrawal"), exports);
|
|
@@ -191,6 +195,12 @@ __exportStar(require("./helpers/generate-idempotency-key-from-order"), exports);
|
|
|
191
195
|
__exportStar(require("./helpers/generate-idempotency-key-from-bulk-payout"), exports);
|
|
192
196
|
__exportStar(require("./helpers/get-is-fireblocks-signature-valid"), exports);
|
|
193
197
|
__exportStar(require("./helpers/get-processor"), exports);
|
|
198
|
+
__exportStar(require("./helpers/resolve-processor"), exports);
|
|
199
|
+
__exportStar(require("./helpers/get-custom-rio-bank-account"), exports);
|
|
200
|
+
__exportStar(require("./helpers/payin-destinations"), exports);
|
|
201
|
+
__exportStar(require("./helpers/payin-verification"), exports);
|
|
202
|
+
__exportStar(require("./helpers/processor-enablement"), exports);
|
|
203
|
+
__exportStar(require("./helpers/record-observed-processor-readiness"), exports);
|
|
194
204
|
__exportStar(require("./helpers/get-bulk-payment-from-reference"), exports);
|
|
195
205
|
__exportStar(require("./helpers/extract-error-message"), exports);
|
|
196
206
|
__exportStar(require("./helpers/get-exchange-rates-with-markups"), exports);
|
|
@@ -39,6 +39,7 @@ const getOrder = (req, res, next, mongoose, onlyBankOrders) => __awaiter(void 0,
|
|
|
39
39
|
common_1.Processor.SPID,
|
|
40
40
|
common_1.Processor.SPEI_NVIO,
|
|
41
41
|
common_1.Processor.SPEI_STP,
|
|
42
|
+
common_1.Processor.SPEI_FINTOC,
|
|
42
43
|
].includes(order.processor)) {
|
|
43
44
|
req.order = order;
|
|
44
45
|
}
|
|
@@ -6,7 +6,7 @@ interface BankAccountVerificationAttrs {
|
|
|
6
6
|
bankAccountId: string;
|
|
7
7
|
status: BankAccountVerificationStatus;
|
|
8
8
|
amount: number;
|
|
9
|
-
provider?: Processor.SPEI_STP | Processor.SPEI_NVIO | Processor.Alfin;
|
|
9
|
+
provider?: Processor.SPEI_STP | Processor.SPEI_NVIO | Processor.Alfin | Processor.SPEI_FINTOC;
|
|
10
10
|
providerWithdrawalId?: string;
|
|
11
11
|
SPEITrackingNumber?: string;
|
|
12
12
|
CEPLink?: string;
|
|
@@ -21,7 +21,7 @@ interface BankAccountVerificationDoc extends Document {
|
|
|
21
21
|
bankAccountId: string;
|
|
22
22
|
status: BankAccountVerificationStatus;
|
|
23
23
|
amount: number;
|
|
24
|
-
provider?: Processor.SPEI_STP | Processor.SPEI_NVIO | Processor.Alfin;
|
|
24
|
+
provider?: Processor.SPEI_STP | Processor.SPEI_NVIO | Processor.Alfin | Processor.SPEI_FINTOC;
|
|
25
25
|
providerWithdrawalId?: string;
|
|
26
26
|
SPEITrackingNumber?: string;
|
|
27
27
|
CEPLink?: string;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Mongoose, Model, Document, HydratedDocument } from "mongoose";
|
|
2
|
+
interface FintocDepositCLABEAttrs {
|
|
3
|
+
createdAt: Date;
|
|
4
|
+
userId: string;
|
|
5
|
+
CLABE: string;
|
|
6
|
+
fintocAccountNumberId?: string;
|
|
7
|
+
processedFintocEventIds?: string[];
|
|
8
|
+
orderId?: string;
|
|
9
|
+
metadata?: Record<string, string>;
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
disabledAt?: Date;
|
|
12
|
+
}
|
|
13
|
+
interface FintocDepositCLABEDoc extends Document {
|
|
14
|
+
createdAt: Date;
|
|
15
|
+
userId: string;
|
|
16
|
+
CLABE: string;
|
|
17
|
+
fintocAccountNumberId?: string;
|
|
18
|
+
processedFintocEventIds?: string[];
|
|
19
|
+
orderId?: string;
|
|
20
|
+
metadata?: Record<string, string>;
|
|
21
|
+
disabled?: boolean;
|
|
22
|
+
disabledAt?: Date;
|
|
23
|
+
}
|
|
24
|
+
interface FintocDepositCLABEModel extends Model<FintocDepositCLABEDoc> {
|
|
25
|
+
build(attrs: FintocDepositCLABEAttrs): HydratedDocument<FintocDepositCLABEDoc>;
|
|
26
|
+
}
|
|
27
|
+
declare const buildFintocDepositCLABE: (mongoose: Mongoose) => FintocDepositCLABEModel;
|
|
28
|
+
export { buildFintocDepositCLABE, FintocDepositCLABEDoc, FintocDepositCLABEAttrs, };
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildFintocDepositCLABE = void 0;
|
|
4
|
+
const buildFintocDepositCLABE = (mongoose) => {
|
|
5
|
+
if (mongoose.models.FintocDepositCLABE) {
|
|
6
|
+
return mongoose.model("FintocDepositCLABE");
|
|
7
|
+
}
|
|
8
|
+
const FintocDepositCLABESchema = new mongoose.Schema({
|
|
9
|
+
userId: {
|
|
10
|
+
type: String,
|
|
11
|
+
},
|
|
12
|
+
CLABE: {
|
|
13
|
+
type: String,
|
|
14
|
+
},
|
|
15
|
+
fintocAccountNumberId: {
|
|
16
|
+
type: String,
|
|
17
|
+
},
|
|
18
|
+
processedFintocEventIds: {
|
|
19
|
+
type: [String],
|
|
20
|
+
default: [],
|
|
21
|
+
},
|
|
22
|
+
orderId: {
|
|
23
|
+
type: String,
|
|
24
|
+
index: { unique: true, sparse: true },
|
|
25
|
+
},
|
|
26
|
+
metadata: {
|
|
27
|
+
type: mongoose.Schema.Types.Mixed,
|
|
28
|
+
},
|
|
29
|
+
disabled: {
|
|
30
|
+
type: Boolean,
|
|
31
|
+
default: false,
|
|
32
|
+
},
|
|
33
|
+
disabledAt: {
|
|
34
|
+
type: mongoose.Schema.Types.Date,
|
|
35
|
+
},
|
|
36
|
+
createdAt: {
|
|
37
|
+
type: mongoose.Schema.Types.Date,
|
|
38
|
+
required: true,
|
|
39
|
+
},
|
|
40
|
+
}, {
|
|
41
|
+
toJSON: {
|
|
42
|
+
transform(doc, ret) {
|
|
43
|
+
ret.id = ret._id.valueOf();
|
|
44
|
+
delete ret._id;
|
|
45
|
+
delete ret.__v;
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
FintocDepositCLABESchema.index({ userId: 1 }, { unique: true });
|
|
50
|
+
FintocDepositCLABESchema.statics.build = (attrs) => {
|
|
51
|
+
return new FintocDepositCLABE(attrs);
|
|
52
|
+
};
|
|
53
|
+
const FintocDepositCLABE = mongoose.model("FintocDepositCLABE", FintocDepositCLABESchema);
|
|
54
|
+
return FintocDepositCLABE;
|
|
55
|
+
};
|
|
56
|
+
exports.buildFintocDepositCLABE = buildFintocDepositCLABE;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { FintocMXNWithdrawalStatus } from "@riocrypto/common";
|
|
2
|
+
import { Mongoose, Model, Document, HydratedDocument } from "mongoose";
|
|
3
|
+
interface FintocMXNWithdrawalAttrs {
|
|
4
|
+
createdAt: Date;
|
|
5
|
+
type: "transaction" | "bankAccountVerification" | "liquidityOrder" | "internalTransfer";
|
|
6
|
+
orderId?: string;
|
|
7
|
+
numberOfParts?: number;
|
|
8
|
+
partsCompleted?: number;
|
|
9
|
+
bankAccountVerificationId?: string;
|
|
10
|
+
bulkBankPayoutId?: string;
|
|
11
|
+
internalTransferId?: string;
|
|
12
|
+
withdrawalIdempotencyKey?: string;
|
|
13
|
+
FintocWithdrawals: {
|
|
14
|
+
uuid: string;
|
|
15
|
+
fintocTransferId?: string;
|
|
16
|
+
trackingKey?: string;
|
|
17
|
+
idempotencyKey?: string;
|
|
18
|
+
partNumber: number;
|
|
19
|
+
amount: number;
|
|
20
|
+
reference: string;
|
|
21
|
+
status: FintocMXNWithdrawalStatus;
|
|
22
|
+
}[];
|
|
23
|
+
orderVersion?: number;
|
|
24
|
+
}
|
|
25
|
+
interface FintocMXNWithdrawalDoc extends Document {
|
|
26
|
+
createdAt: Date;
|
|
27
|
+
type: "transaction" | "bankAccountVerification" | "liquidityOrder" | "internalTransfer";
|
|
28
|
+
orderId?: string;
|
|
29
|
+
bankAccountVerificationId?: string;
|
|
30
|
+
numberOfParts?: number;
|
|
31
|
+
bulkBankPayoutId?: string;
|
|
32
|
+
internalTransferId?: string;
|
|
33
|
+
withdrawalIdempotencyKey?: string;
|
|
34
|
+
partsCompleted?: number;
|
|
35
|
+
orderVersion?: number;
|
|
36
|
+
FintocWithdrawals: {
|
|
37
|
+
uuid: string;
|
|
38
|
+
fintocTransferId?: string;
|
|
39
|
+
trackingKey?: string;
|
|
40
|
+
idempotencyKey?: string;
|
|
41
|
+
partNumber: number;
|
|
42
|
+
amount: number;
|
|
43
|
+
status: FintocMXNWithdrawalStatus;
|
|
44
|
+
reference: string;
|
|
45
|
+
}[];
|
|
46
|
+
}
|
|
47
|
+
interface FintocMXNWithdrawalModel extends Model<FintocMXNWithdrawalDoc> {
|
|
48
|
+
build(attrs: FintocMXNWithdrawalAttrs): HydratedDocument<FintocMXNWithdrawalDoc>;
|
|
49
|
+
}
|
|
50
|
+
declare const buildFintocMXNWithdrawal: (mongoose: Mongoose) => FintocMXNWithdrawalModel;
|
|
51
|
+
export { buildFintocMXNWithdrawal, FintocMXNWithdrawalDoc, FintocMXNWithdrawalAttrs, };
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildFintocMXNWithdrawal = void 0;
|
|
4
|
+
const common_1 = require("@riocrypto/common");
|
|
5
|
+
const buildFintocMXNWithdrawal = (mongoose) => {
|
|
6
|
+
if (mongoose.models.FintocMXNWithdrawal) {
|
|
7
|
+
return mongoose.model("FintocMXNWithdrawal");
|
|
8
|
+
}
|
|
9
|
+
const FintocMXNWithdrawalSchema = new mongoose.Schema({
|
|
10
|
+
orderId: {
|
|
11
|
+
type: String,
|
|
12
|
+
index: { unique: true, sparse: true },
|
|
13
|
+
},
|
|
14
|
+
bankAccountVerificationId: {
|
|
15
|
+
type: String,
|
|
16
|
+
index: { unique: true, sparse: true },
|
|
17
|
+
},
|
|
18
|
+
internalTransferId: {
|
|
19
|
+
type: String,
|
|
20
|
+
index: { unique: true, sparse: true },
|
|
21
|
+
},
|
|
22
|
+
withdrawalIdempotencyKey: {
|
|
23
|
+
type: String,
|
|
24
|
+
index: { unique: true, sparse: true },
|
|
25
|
+
},
|
|
26
|
+
bulkBankPayoutId: {
|
|
27
|
+
type: String,
|
|
28
|
+
index: { unique: true, sparse: true },
|
|
29
|
+
},
|
|
30
|
+
numberOfParts: {
|
|
31
|
+
type: Number,
|
|
32
|
+
},
|
|
33
|
+
partsCompleted: {
|
|
34
|
+
type: Number,
|
|
35
|
+
},
|
|
36
|
+
type: {
|
|
37
|
+
type: String,
|
|
38
|
+
required: true,
|
|
39
|
+
},
|
|
40
|
+
createdAt: {
|
|
41
|
+
type: mongoose.Schema.Types.Date,
|
|
42
|
+
required: true,
|
|
43
|
+
},
|
|
44
|
+
FintocWithdrawals: {
|
|
45
|
+
type: [
|
|
46
|
+
{
|
|
47
|
+
uuid: String,
|
|
48
|
+
fintocTransferId: String,
|
|
49
|
+
trackingKey: String,
|
|
50
|
+
idempotencyKey: String,
|
|
51
|
+
amount: Number,
|
|
52
|
+
status: {
|
|
53
|
+
type: String,
|
|
54
|
+
enum: Object.values(common_1.FintocMXNWithdrawalStatus),
|
|
55
|
+
},
|
|
56
|
+
partNumber: Number,
|
|
57
|
+
reference: String,
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
},
|
|
61
|
+
orderVersion: {
|
|
62
|
+
type: Number,
|
|
63
|
+
},
|
|
64
|
+
}, {
|
|
65
|
+
toJSON: {
|
|
66
|
+
transform(doc, ret) {
|
|
67
|
+
ret.id = ret._id.valueOf();
|
|
68
|
+
delete ret._id;
|
|
69
|
+
delete ret.__v;
|
|
70
|
+
if (ret.FintocWithdrawals && Array.isArray(ret.FintocWithdrawals)) {
|
|
71
|
+
ret.FintocWithdrawals = ret.FintocWithdrawals.map((withdrawal) => {
|
|
72
|
+
if (withdrawal._id) {
|
|
73
|
+
withdrawal.id = withdrawal._id.valueOf();
|
|
74
|
+
delete withdrawal._id;
|
|
75
|
+
}
|
|
76
|
+
return withdrawal;
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
FintocMXNWithdrawalSchema.statics.build = (attrs) => {
|
|
83
|
+
return new FintocMXNWithdrawal(attrs);
|
|
84
|
+
};
|
|
85
|
+
const FintocMXNWithdrawal = mongoose.model("FintocMXNWithdrawal", FintocMXNWithdrawalSchema);
|
|
86
|
+
return FintocMXNWithdrawal;
|
|
87
|
+
};
|
|
88
|
+
exports.buildFintocMXNWithdrawal = buildFintocMXNWithdrawal;
|
|
@@ -18,6 +18,10 @@ interface FireblocksVaultAttrs {
|
|
|
18
18
|
bulkCryptoPaymentId: string;
|
|
19
19
|
crypto: Crypto;
|
|
20
20
|
}[];
|
|
21
|
+
activePaymentAddressVerifications?: {
|
|
22
|
+
verificationId: string;
|
|
23
|
+
crypto: Crypto;
|
|
24
|
+
}[];
|
|
21
25
|
}
|
|
22
26
|
interface FireblocksVaultDoc extends mongoose.Document {
|
|
23
27
|
userId: string;
|
|
@@ -37,6 +41,10 @@ interface FireblocksVaultDoc extends mongoose.Document {
|
|
|
37
41
|
bulkCryptoPaymentId: string;
|
|
38
42
|
crypto: Crypto;
|
|
39
43
|
}[];
|
|
44
|
+
activePaymentAddressVerifications?: {
|
|
45
|
+
verificationId: string;
|
|
46
|
+
crypto: Crypto;
|
|
47
|
+
}[];
|
|
40
48
|
}
|
|
41
49
|
interface FireblocksVaultModel extends mongoose.Model<FireblocksVaultDoc> {
|
|
42
50
|
build(attrs: FireblocksVaultAttrs): HydratedDocument<FireblocksVaultDoc>;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { Crypto, ProcessorReadinessStatus, ProcessorReadinessVerificationMethod } from "@riocrypto/common";
|
|
2
|
+
import { Mongoose, Model, Document, HydratedDocument } from "mongoose";
|
|
3
|
+
interface PaymentAddressVerificationAttrs {
|
|
4
|
+
createdAt: Date;
|
|
5
|
+
userId: string;
|
|
6
|
+
crypto: Crypto;
|
|
7
|
+
fireblocksVaultId: string;
|
|
8
|
+
address: string;
|
|
9
|
+
memo?: string;
|
|
10
|
+
status: ProcessorReadinessStatus;
|
|
11
|
+
testAmount?: number;
|
|
12
|
+
observedTransfer?: {
|
|
13
|
+
amount: number;
|
|
14
|
+
blockchainTxId?: string;
|
|
15
|
+
fireblocksTransferId?: string;
|
|
16
|
+
originBlockchainAddress?: string;
|
|
17
|
+
receivedAt: Date;
|
|
18
|
+
};
|
|
19
|
+
verifiedAt?: Date;
|
|
20
|
+
verifiedVia?: ProcessorReadinessVerificationMethod;
|
|
21
|
+
verifiedByAdminId?: string;
|
|
22
|
+
verificationNote?: string;
|
|
23
|
+
}
|
|
24
|
+
interface PaymentAddressVerificationDoc extends Document {
|
|
25
|
+
createdAt: Date;
|
|
26
|
+
userId: string;
|
|
27
|
+
crypto: Crypto;
|
|
28
|
+
fireblocksVaultId: string;
|
|
29
|
+
address: string;
|
|
30
|
+
memo?: string;
|
|
31
|
+
status: ProcessorReadinessStatus;
|
|
32
|
+
testAmount?: number;
|
|
33
|
+
observedTransfer?: {
|
|
34
|
+
amount: number;
|
|
35
|
+
blockchainTxId?: string;
|
|
36
|
+
fireblocksTransferId?: string;
|
|
37
|
+
originBlockchainAddress?: string;
|
|
38
|
+
receivedAt: Date;
|
|
39
|
+
};
|
|
40
|
+
verifiedAt?: Date;
|
|
41
|
+
verifiedVia?: ProcessorReadinessVerificationMethod;
|
|
42
|
+
verifiedByAdminId?: string;
|
|
43
|
+
verificationNote?: string;
|
|
44
|
+
}
|
|
45
|
+
interface PaymentAddressVerificationModel extends Model<PaymentAddressVerificationDoc> {
|
|
46
|
+
build(attrs: PaymentAddressVerificationAttrs): HydratedDocument<PaymentAddressVerificationDoc>;
|
|
47
|
+
}
|
|
48
|
+
declare const buildPaymentAddressVerification: (mongoose: Mongoose) => PaymentAddressVerificationModel;
|
|
49
|
+
export { buildPaymentAddressVerification, PaymentAddressVerificationDoc, PaymentAddressVerificationAttrs, };
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildPaymentAddressVerification = void 0;
|
|
4
|
+
// What we have proven about one crypto address a user pays us at. See the
|
|
5
|
+
// PaymentAddressVerification type in common for why this exists and why it is
|
|
6
|
+
// keyed by vault rather than by address.
|
|
7
|
+
const buildPaymentAddressVerification = (mongoose) => {
|
|
8
|
+
if (mongoose.models.PaymentAddressVerification) {
|
|
9
|
+
return mongoose.model("PaymentAddressVerification");
|
|
10
|
+
}
|
|
11
|
+
const PaymentAddressVerificationSchema = new mongoose.Schema({
|
|
12
|
+
userId: {
|
|
13
|
+
type: String,
|
|
14
|
+
required: true,
|
|
15
|
+
},
|
|
16
|
+
crypto: {
|
|
17
|
+
type: String,
|
|
18
|
+
required: true,
|
|
19
|
+
},
|
|
20
|
+
fireblocksVaultId: {
|
|
21
|
+
type: String,
|
|
22
|
+
required: true,
|
|
23
|
+
},
|
|
24
|
+
address: {
|
|
25
|
+
type: String,
|
|
26
|
+
required: true,
|
|
27
|
+
},
|
|
28
|
+
memo: {
|
|
29
|
+
type: String,
|
|
30
|
+
},
|
|
31
|
+
status: {
|
|
32
|
+
type: String,
|
|
33
|
+
required: true,
|
|
34
|
+
},
|
|
35
|
+
testAmount: {
|
|
36
|
+
type: Number,
|
|
37
|
+
},
|
|
38
|
+
observedTransfer: {
|
|
39
|
+
type: Object,
|
|
40
|
+
},
|
|
41
|
+
verifiedAt: {
|
|
42
|
+
type: mongoose.Schema.Types.Date,
|
|
43
|
+
},
|
|
44
|
+
verifiedVia: {
|
|
45
|
+
type: String,
|
|
46
|
+
},
|
|
47
|
+
verifiedByAdminId: {
|
|
48
|
+
type: String,
|
|
49
|
+
},
|
|
50
|
+
verificationNote: {
|
|
51
|
+
type: String,
|
|
52
|
+
},
|
|
53
|
+
createdAt: {
|
|
54
|
+
type: mongoose.Schema.Types.Date,
|
|
55
|
+
required: true,
|
|
56
|
+
},
|
|
57
|
+
}, {
|
|
58
|
+
toJSON: {
|
|
59
|
+
transform(doc, ret) {
|
|
60
|
+
ret.id = ret._id.valueOf();
|
|
61
|
+
delete ret._id;
|
|
62
|
+
delete ret.__v;
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
// One record per address, where an address is a vault and an asset. Unique
|
|
67
|
+
// because the inbound webhook and a customer starting a test can arrive at the
|
|
68
|
+
// same moment, and two records disagreeing about status would let a test
|
|
69
|
+
// deposit match a row that nobody is looking at.
|
|
70
|
+
PaymentAddressVerificationSchema.index({ userId: 1, crypto: 1, fireblocksVaultId: 1 }, { unique: true });
|
|
71
|
+
PaymentAddressVerificationSchema.statics.build = (attrs) => {
|
|
72
|
+
return new PaymentAddressVerification(attrs);
|
|
73
|
+
};
|
|
74
|
+
const PaymentAddressVerification = mongoose.model("PaymentAddressVerification", PaymentAddressVerificationSchema);
|
|
75
|
+
return PaymentAddressVerification;
|
|
76
|
+
};
|
|
77
|
+
exports.buildPaymentAddressVerification = buildPaymentAddressVerification;
|