@riocrypto/common-server 1.0.2776 → 1.0.2779

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.
@@ -0,0 +1,17 @@
1
+ import { Country, Side, User } from "@riocrypto/common";
2
+ /**
3
+ * Walks the user's tier ranges from the current tier (matched by amount)
4
+ * down to lower tiers, returning the first defined interpolated rate.
5
+ *
6
+ * Mirrors the tier-walk used in fee resolution so a higher tier whose
7
+ * forward curve omits a day can still inherit from a lower tier with a more
8
+ * complete curve. Returns undefined if no tier matches the amount or no
9
+ * tier contains the requested day.
10
+ */
11
+ export declare const findUserTierForwardCurveRate: ({ user, country, side, amount, day, }: {
12
+ user: User | undefined | null;
13
+ country: Country;
14
+ side: Side;
15
+ amount: number;
16
+ day: number;
17
+ }) => number | undefined;
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.findUserTierForwardCurveRate = void 0;
4
+ const interpolate_forward_curve_rate_1 = require("./interpolate-forward-curve-rate");
5
+ /**
6
+ * Walks the user's tier ranges from the current tier (matched by amount)
7
+ * down to lower tiers, returning the first defined interpolated rate.
8
+ *
9
+ * Mirrors the tier-walk used in fee resolution so a higher tier whose
10
+ * forward curve omits a day can still inherit from a lower tier with a more
11
+ * complete curve. Returns undefined if no tier matches the amount or no
12
+ * tier contains the requested day.
13
+ */
14
+ const findUserTierForwardCurveRate = ({ user, country, side, amount, day, }) => {
15
+ var _a, _b;
16
+ const ranges = (_b = (_a = user === null || user === void 0 ? void 0 : user.platformFeeRanges) === null || _a === void 0 ? void 0 : _a[country]) === null || _b === void 0 ? void 0 : _b[side];
17
+ if (!ranges || ranges.length === 0)
18
+ return undefined;
19
+ const sorted = [...ranges].sort((a, b) => a.min - b.min);
20
+ let currentRangeIndex = -1;
21
+ for (let i = 0; i < sorted.length; i++) {
22
+ const range = sorted[i];
23
+ if (range.min <= amount && range.max >= amount) {
24
+ currentRangeIndex = i;
25
+ break;
26
+ }
27
+ }
28
+ if (currentRangeIndex === -1 &&
29
+ sorted.length > 0 &&
30
+ amount > sorted[sorted.length - 1].max) {
31
+ currentRangeIndex = sorted.length - 1;
32
+ }
33
+ if (currentRangeIndex === -1)
34
+ return undefined;
35
+ for (let i = currentRangeIndex; i >= 0; i--) {
36
+ const rate = (0, interpolate_forward_curve_rate_1.interpolateForwardCurveRate)(sorted[i].twoWaySettlementDateOffsetFee, day);
37
+ if (rate !== undefined)
38
+ return rate;
39
+ }
40
+ return undefined;
41
+ };
42
+ exports.findUserTierForwardCurveRate = findUserTierForwardCurveRate;
@@ -0,0 +1,35 @@
1
+ import { Country, RioSettings, Side, User } from "@riocrypto/common";
2
+ export type ResolvedForwardCurveTier = {
3
+ min: number;
4
+ max: number;
5
+ /**
6
+ * Anchor points keyed by day (string for transport / MongoDB
7
+ * compatibility) -> rate (decimal, e.g. 0.0005 = 5 BPS).
8
+ *
9
+ * The set of keys is the union of every day defined by any layer relevant
10
+ * to this tier (user tier, lower user tiers, broker tiers, platform
11
+ * default). At each key the resolved value is what the trader would
12
+ * actually be charged at that T+n, so visual interpolation between anchor
13
+ * points produces a single continuous curve covering the full range.
14
+ */
15
+ curve: {
16
+ [day: string]: number;
17
+ };
18
+ };
19
+ /**
20
+ * Builds per-tier resolved forward curves suitable for charting.
21
+ *
22
+ * Tiers come from the user's amount tiers when defined, otherwise from the
23
+ * broker's tiers, otherwise a single synthetic tier covering the platform
24
+ * default. For each tier, every "anchor day" defined anywhere in the
25
+ * fallback chain is filled with the resolved rate at that day; the chart
26
+ * can then linearly interpolate between anchors to render a single
27
+ * continuous line.
28
+ */
29
+ export declare const getResolvedForwardCurveTiers: ({ user, broker, country, side, rioSettings, }: {
30
+ user: User;
31
+ broker?: User | null | undefined;
32
+ country: Country;
33
+ side: Side;
34
+ rioSettings: Pick<RioSettings, "defaultTwoWaySettlementDateOffsetFee">;
35
+ }) => ResolvedForwardCurveTier[];
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getResolvedForwardCurveTiers = void 0;
4
+ const resolve_forward_curve_rate_1 = require("./resolve-forward-curve-rate");
5
+ /**
6
+ * Builds per-tier resolved forward curves suitable for charting.
7
+ *
8
+ * Tiers come from the user's amount tiers when defined, otherwise from the
9
+ * broker's tiers, otherwise a single synthetic tier covering the platform
10
+ * default. For each tier, every "anchor day" defined anywhere in the
11
+ * fallback chain is filled with the resolved rate at that day; the chart
12
+ * can then linearly interpolate between anchors to render a single
13
+ * continuous line.
14
+ */
15
+ const getResolvedForwardCurveTiers = ({ user, broker, country, side, rioSettings, }) => {
16
+ var _a, _b, _c, _d, _e, _f;
17
+ const userRanges = (_b = (_a = user.platformFeeRanges) === null || _a === void 0 ? void 0 : _a[country]) === null || _b === void 0 ? void 0 : _b[side];
18
+ const brokerRanges = (_d = (_c = broker === null || broker === void 0 ? void 0 : broker.platformFeeRanges) === null || _c === void 0 ? void 0 : _c[country]) === null || _d === void 0 ? void 0 : _d[side];
19
+ const platformCurve = (_f = (_e = rioSettings.defaultTwoWaySettlementDateOffsetFee) === null || _e === void 0 ? void 0 : _e[country]) === null || _f === void 0 ? void 0 : _f[side];
20
+ let tiers = [];
21
+ if (userRanges && userRanges.length > 0) {
22
+ tiers = [...userRanges]
23
+ .sort((a, b) => a.min - b.min)
24
+ .map((r) => ({ min: r.min, max: r.max }));
25
+ }
26
+ else if (brokerRanges && brokerRanges.length > 0) {
27
+ tiers = [...brokerRanges]
28
+ .sort((a, b) => a.min - b.min)
29
+ .map((r) => ({ min: r.min, max: r.max }));
30
+ }
31
+ else {
32
+ tiers = [{ min: 0, max: Number.MAX_SAFE_INTEGER }];
33
+ }
34
+ const collectDays = (curve) => {
35
+ if (!curve)
36
+ return [];
37
+ return Object.keys(curve)
38
+ .map((k) => Number(k))
39
+ .filter((d) => Number.isFinite(d));
40
+ };
41
+ const anchorDays = new Set();
42
+ if (userRanges) {
43
+ for (const r of userRanges) {
44
+ collectDays(r.twoWaySettlementDateOffsetFee).forEach((d) => anchorDays.add(d));
45
+ }
46
+ }
47
+ if (brokerRanges) {
48
+ for (const r of brokerRanges) {
49
+ collectDays(r.twoWaySettlementDateOffsetFee).forEach((d) => anchorDays.add(d));
50
+ }
51
+ }
52
+ collectDays(platformCurve).forEach((d) => anchorDays.add(d));
53
+ if (anchorDays.size === 0) {
54
+ return tiers.map((t) => (Object.assign(Object.assign({}, t), { curve: {} })));
55
+ }
56
+ const sortedDays = [...anchorDays].sort((a, b) => a - b);
57
+ return tiers.map((tier) => {
58
+ const sampleAmount = tier.max >= Number.MAX_SAFE_INTEGER
59
+ ? tier.min + 1
60
+ : Math.floor((tier.min + tier.max) / 2);
61
+ const curve = {};
62
+ for (const day of sortedDays) {
63
+ const rate = (0, resolve_forward_curve_rate_1.resolveForwardCurveRate)({
64
+ user,
65
+ broker,
66
+ country,
67
+ side,
68
+ amount: sampleAmount,
69
+ day,
70
+ rioSettings,
71
+ });
72
+ if (rate !== undefined)
73
+ curve[String(day)] = rate;
74
+ }
75
+ return Object.assign(Object.assign({}, tier), { curve });
76
+ });
77
+ };
78
+ exports.getResolvedForwardCurveTiers = getResolvedForwardCurveTiers;
@@ -0,0 +1,15 @@
1
+ export type ForwardCurve = {
2
+ [day: number]: number;
3
+ };
4
+ /**
5
+ * Linearly interpolates a forward curve at a given day.
6
+ *
7
+ * - Returns the rate at the requested day, with linear interpolation between
8
+ * defined points.
9
+ * - Returns undefined if the requested day is outside [minDefinedDay,
10
+ * maxDefinedDay] or if the curve has no defined points.
11
+ *
12
+ * Days outside the defined range are intentionally undefined so callers can
13
+ * fall back to the next layer (broker parent curve or platform default).
14
+ */
15
+ export declare const interpolateForwardCurveRate: (curve: ForwardCurve | undefined, daysUntilSettlementDate: number) => number | undefined;
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.interpolateForwardCurveRate = void 0;
4
+ /**
5
+ * Linearly interpolates a forward curve at a given day.
6
+ *
7
+ * - Returns the rate at the requested day, with linear interpolation between
8
+ * defined points.
9
+ * - Returns undefined if the requested day is outside [minDefinedDay,
10
+ * maxDefinedDay] or if the curve has no defined points.
11
+ *
12
+ * Days outside the defined range are intentionally undefined so callers can
13
+ * fall back to the next layer (broker parent curve or platform default).
14
+ */
15
+ const interpolateForwardCurveRate = (curve, daysUntilSettlementDate) => {
16
+ if (!curve)
17
+ return undefined;
18
+ const definedDays = Object.keys(curve)
19
+ .map((key) => Number(key))
20
+ .filter((day) => Number.isFinite(day) && curve[day] !== undefined)
21
+ .sort((a, b) => a - b);
22
+ if (definedDays.length === 0)
23
+ return undefined;
24
+ const minDay = definedDays[0];
25
+ const maxDay = definedDays[definedDays.length - 1];
26
+ if (daysUntilSettlementDate < minDay || daysUntilSettlementDate > maxDay) {
27
+ return undefined;
28
+ }
29
+ if (curve[daysUntilSettlementDate] !== undefined) {
30
+ return curve[daysUntilSettlementDate];
31
+ }
32
+ let lowerDay = definedDays[0];
33
+ let upperDay = definedDays[definedDays.length - 1];
34
+ for (let i = 0; i < definedDays.length - 1; i++) {
35
+ if (definedDays[i] <= daysUntilSettlementDate &&
36
+ definedDays[i + 1] >= daysUntilSettlementDate) {
37
+ lowerDay = definedDays[i];
38
+ upperDay = definedDays[i + 1];
39
+ break;
40
+ }
41
+ }
42
+ const lowerFee = curve[lowerDay];
43
+ const upperFee = curve[upperDay];
44
+ if (upperDay === lowerDay)
45
+ return lowerFee;
46
+ const slope = (upperFee - lowerFee) / (upperDay - lowerDay);
47
+ return lowerFee + slope * (daysUntilSettlementDate - lowerDay);
48
+ };
49
+ exports.interpolateForwardCurveRate = interpolateForwardCurveRate;
@@ -0,0 +1,19 @@
1
+ import { Country, RioSettings, Side, User } from "@riocrypto/common";
2
+ /**
3
+ * Resolves the effective two-way-settlement-date-offset rate at a given day,
4
+ * walking the full fallback chain:
5
+ * 1. user's own tier curves (current tier and lower)
6
+ * 2. broker parent's tier curves (same logic applied to broker)
7
+ * 3. platform default forward curve from RioSettings
8
+ *
9
+ * Returns undefined only if every layer is missing or out of range.
10
+ */
11
+ export declare const resolveForwardCurveRate: ({ user, broker, country, side, amount, day, rioSettings, }: {
12
+ user: User | undefined | null;
13
+ broker?: User | null | undefined;
14
+ country: Country;
15
+ side: Side;
16
+ amount: number;
17
+ day: number;
18
+ rioSettings: Pick<RioSettings, "defaultTwoWaySettlementDateOffsetFee">;
19
+ }) => number | undefined;
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveForwardCurveRate = void 0;
4
+ const find_user_tier_forward_curve_rate_1 = require("./find-user-tier-forward-curve-rate");
5
+ const interpolate_forward_curve_rate_1 = require("./interpolate-forward-curve-rate");
6
+ /**
7
+ * Resolves the effective two-way-settlement-date-offset rate at a given day,
8
+ * walking the full fallback chain:
9
+ * 1. user's own tier curves (current tier and lower)
10
+ * 2. broker parent's tier curves (same logic applied to broker)
11
+ * 3. platform default forward curve from RioSettings
12
+ *
13
+ * Returns undefined only if every layer is missing or out of range.
14
+ */
15
+ const resolveForwardCurveRate = ({ user, broker, country, side, amount, day, rioSettings, }) => {
16
+ var _a, _b;
17
+ const userRate = (0, find_user_tier_forward_curve_rate_1.findUserTierForwardCurveRate)({
18
+ user,
19
+ country,
20
+ side,
21
+ amount,
22
+ day,
23
+ });
24
+ if (userRate !== undefined)
25
+ return userRate;
26
+ if (broker) {
27
+ const brokerRate = (0, find_user_tier_forward_curve_rate_1.findUserTierForwardCurveRate)({
28
+ user: broker,
29
+ country,
30
+ side,
31
+ amount,
32
+ day,
33
+ });
34
+ if (brokerRate !== undefined)
35
+ return brokerRate;
36
+ }
37
+ return (0, interpolate_forward_curve_rate_1.interpolateForwardCurveRate)((_b = (_a = rioSettings.defaultTwoWaySettlementDateOffsetFee) === null || _a === void 0 ? void 0 : _a[country]) === null || _b === void 0 ? void 0 : _b[side], day);
38
+ };
39
+ exports.resolveForwardCurveRate = resolveForwardCurveRate;
package/build/index.d.ts CHANGED
@@ -166,3 +166,7 @@ export * from "./helpers/extract-error-message";
166
166
  export * from "./helpers/get-exchange-rates-with-markups";
167
167
  export * from "./helpers/get-order-from-static-reference";
168
168
  export * from "./helpers/is-after-hours";
169
+ export * from "./helpers/interpolate-forward-curve-rate";
170
+ export * from "./helpers/find-user-tier-forward-curve-rate";
171
+ export * from "./helpers/resolve-forward-curve-rate";
172
+ export * from "./helpers/get-resolved-forward-curve-tiers";
package/build/index.js CHANGED
@@ -182,3 +182,7 @@ __exportStar(require("./helpers/extract-error-message"), exports);
182
182
  __exportStar(require("./helpers/get-exchange-rates-with-markups"), exports);
183
183
  __exportStar(require("./helpers/get-order-from-static-reference"), exports);
184
184
  __exportStar(require("./helpers/is-after-hours"), exports);
185
+ __exportStar(require("./helpers/interpolate-forward-curve-rate"), exports);
186
+ __exportStar(require("./helpers/find-user-tier-forward-curve-rate"), exports);
187
+ __exportStar(require("./helpers/resolve-forward-curve-rate"), exports);
188
+ __exportStar(require("./helpers/get-resolved-forward-curve-tiers"), exports);
@@ -7,6 +7,7 @@ interface AddressVerificationAttrs {
7
7
  status: AddressVerificationStatus;
8
8
  amount: number;
9
9
  blockchainTxId?: string;
10
+ sentAt?: Date;
10
11
  }
11
12
  interface AddressVerificationModel extends Model<AddressVerificationDoc> {
12
13
  build(attrs: AddressVerificationAttrs): HydratedDocument<AddressVerificationDoc>;
@@ -18,6 +19,7 @@ interface AddressVerificationDoc extends Document {
18
19
  status: AddressVerificationStatus;
19
20
  amount: number;
20
21
  blockchainTxId?: string;
22
+ sentAt?: Date;
21
23
  }
22
24
  declare const buildAddressVerification: (mongoose: Mongoose) => AddressVerificationModel;
23
25
  export { buildAddressVerification, AddressVerificationDoc, AddressVerificationAttrs, };
@@ -28,6 +28,9 @@ const buildAddressVerification = (mongoose) => {
28
28
  blockchainTxId: {
29
29
  type: String,
30
30
  },
31
+ sentAt: {
32
+ type: Date,
33
+ },
31
34
  }, {
32
35
  toJSON: {
33
36
  transform(doc, ret) {
@@ -10,6 +10,7 @@ interface BankAccountVerificationAttrs {
10
10
  providerWithdrawalId?: string;
11
11
  SPEITrackingNumber?: string;
12
12
  CEPLink?: string;
13
+ sentAt?: Date;
13
14
  }
14
15
  interface BankAccountVerificationModel extends Model<BankAccountVerificationDoc> {
15
16
  build(attrs: BankAccountVerificationAttrs): HydratedDocument<BankAccountVerificationDoc>;
@@ -24,6 +25,7 @@ interface BankAccountVerificationDoc extends Document {
24
25
  providerWithdrawalId?: string;
25
26
  SPEITrackingNumber?: string;
26
27
  CEPLink?: string;
28
+ sentAt?: Date;
27
29
  }
28
30
  declare const buildBankAccountVerification: (mongoose: Mongoose) => BankAccountVerificationModel;
29
31
  export { buildBankAccountVerification, BankAccountVerificationDoc, BankAccountVerificationAttrs, };
@@ -41,6 +41,9 @@ const buildBankAccountVerification = (mongoose) => {
41
41
  type: String,
42
42
  required: false,
43
43
  },
44
+ sentAt: {
45
+ type: Date,
46
+ },
44
47
  }, {
45
48
  toJSON: {
46
49
  transform(doc, ret) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@riocrypto/common-server",
3
- "version": "1.0.2776",
3
+ "version": "1.0.2779",
4
4
  "description": "",
5
5
  "main": "./build/index.js",
6
6
  "types": "./build/index.d.ts",
@@ -24,7 +24,7 @@
24
24
  "@google-cloud/secret-manager": "^5.6.0",
25
25
  "@google-cloud/storage": "^7.19.0",
26
26
  "@hyperdx/node-opentelemetry": "^0.10.3",
27
- "@riocrypto/common": "1.0.2570",
27
+ "@riocrypto/common": "1.0.2579",
28
28
  "@slack/web-api": "^7.15.0",
29
29
  "@types/express": "^4.17.25",
30
30
  "axios": "1.13.6",