@riocrypto/common-server 1.0.2787 → 1.0.2789

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.
@@ -35,6 +35,19 @@ const NON_COSIGNER_PROVIDERS = new Set([
35
35
  common_1.FXProvider.Matching,
36
36
  common_1.FXProvider.Other,
37
37
  ]);
38
+ /**
39
+ * Providers for which a `tradeAsTwoWaySettlementDateOffset` override on
40
+ * the band is meaningful. Matching is internal book netting and has no
41
+ * upstream tenor; Other is the manual fallback. The runtime ignores the
42
+ * override for these providers even if it was somehow persisted on the
43
+ * band, so a stale value can never accidentally affect routing.
44
+ */
45
+ const PROVIDERS_SUPPORTING_TRADE_AS_OVERRIDE = new Set([
46
+ common_1.FXProvider.Emarkets,
47
+ common_1.FXProvider.Transnetwork,
48
+ common_1.FXProvider.StoneX,
49
+ ]);
50
+ const isOverrideAllowedForProvider = (provider) => PROVIDERS_SUPPORTING_TRADE_AS_OVERRIDE.has(provider);
38
51
  const FALLBACK_RESOLUTION = {
39
52
  provider: common_1.FXProvider.Other,
40
53
  automatic: true,
@@ -272,7 +285,16 @@ const resolveFXProviderForAmount = (policy, fiat, amountFiat, offset, now = new
272
285
  if (!matchedAmountRange) {
273
286
  return Object.assign(Object.assign({}, FALLBACK_RESOLUTION), { executionThresholdMs });
274
287
  }
275
- if (!isProviderEligible(matchedAmountRange.provider, fiat, amountFiat, offset)) {
288
+ // Eligibility is checked against the *effective* offset (the override
289
+ // when set, otherwise the trade's own offset). This lets an operator
290
+ // route a T+0 band to StoneX by overriding to T+1, or a T+3 band to
291
+ // Emarkets/Transnetwork by overriding to T+2 - the upstream provider
292
+ // only ever sees the override.
293
+ const tradeAsTwoWaySettlementDateOffset = isOverrideAllowedForProvider(matchedAmountRange.provider)
294
+ ? matchedAmountRange.tradeAsTwoWaySettlementDateOffset
295
+ : undefined;
296
+ const effectiveOffset = tradeAsTwoWaySettlementDateOffset !== null && tradeAsTwoWaySettlementDateOffset !== void 0 ? tradeAsTwoWaySettlementDateOffset : offset;
297
+ if (!isProviderEligible(matchedAmountRange.provider, fiat, amountFiat, effectiveOffset)) {
276
298
  return Object.assign(Object.assign({}, FALLBACK_RESOLUTION), { executionThresholdMs });
277
299
  }
278
300
  const automatic = NON_COSIGNER_PROVIDERS.has(matchedAmountRange.provider)
@@ -282,6 +304,7 @@ const resolveFXProviderForAmount = (policy, fiat, amountFiat, offset, now = new
282
304
  provider: matchedAmountRange.provider,
283
305
  automatic,
284
306
  executionThresholdMs,
307
+ tradeAsTwoWaySettlementDateOffset,
285
308
  };
286
309
  };
287
310
  exports.resolveFXProviderForAmount = resolveFXProviderForAmount;
@@ -10,8 +10,34 @@ interface FXTradeAttrs {
10
10
  amountTraded: number;
11
11
  price?: number;
12
12
  provider: FXProvider;
13
+ /**
14
+ * Operative settlement (what the trade is *hedged* at). Equals the
15
+ * underlying settlement unless the matched FX trading policy band
16
+ * carries a `tradeAsTwoWaySettlementDateOffset` override (or the
17
+ * cosigner-notification webhook picked an alternative settlement
18
+ * type during approval), in which case it is the post-override
19
+ * value. This is what `place-fx-trade-external-trade` and
20
+ * `send-fx-trade-cosigner-request` consume - they only care about
21
+ * the tenor we will actually trade at upstream.
22
+ */
13
23
  twoWaySettlementDate: Date;
14
24
  twoWaySettlementDateOffset: number;
25
+ /**
26
+ * Customer-facing settlement derived from the underlying order(s).
27
+ * Immutable for the lifetime of the FX trade and used for:
28
+ * - policy lookup (`getFXTradingPolicy` is keyed on what the
29
+ * customer was promised, not on our hedging tenor);
30
+ * - aggregation grouping (two orders that promised the customer
31
+ * different days cannot share an FX trade even if the operative
32
+ * hedge tenor would be the same).
33
+ *
34
+ * Marked optional on the type for backwards-compat with trades
35
+ * created before this field existed; runtime readers fall back to
36
+ * the operative fields when missing. New writers always populate
37
+ * both.
38
+ */
39
+ underlyingTwoWaySettlementDate?: Date;
40
+ underlyingTwoWaySettlementDateOffset?: number;
15
41
  executedTrades: {
16
42
  amount: number;
17
43
  provider: FXProvider;
@@ -36,6 +62,8 @@ interface FXTradeDoc extends Document {
36
62
  provider: FXProvider;
37
63
  twoWaySettlementDate: Date;
38
64
  twoWaySettlementDateOffset: number;
65
+ underlyingTwoWaySettlementDate?: Date;
66
+ underlyingTwoWaySettlementDateOffset?: number;
39
67
  executedTrades: {
40
68
  amount: number;
41
69
  provider: FXProvider;
@@ -33,6 +33,12 @@ const buildFXTrade = (mongoose) => {
33
33
  twoWaySettlementDateOffset: {
34
34
  type: Number,
35
35
  },
36
+ underlyingTwoWaySettlementDate: {
37
+ type: mongoose.Schema.Types.Date,
38
+ },
39
+ underlyingTwoWaySettlementDateOffset: {
40
+ type: Number,
41
+ },
36
42
  amountTraded: {
37
43
  type: Number,
38
44
  required: true,
@@ -1,4 +1,4 @@
1
- import { Country, DeferredPaymentType, EmarketsSettlementType, Fiat, FXProvider, FXTradingPolicies, Processor, Side, TransnetworkSettlementType } from "@riocrypto/common";
1
+ import { Country, DeferredPaymentType, Fiat, FXProvider, FXTradingPolicies, Processor, Side } from "@riocrypto/common";
2
2
  import { TVFXDataProvider } from "@riocrypto/common";
3
3
  import mongoose, { HydratedDocument } from "mongoose";
4
4
  interface RioSettingsAttrs {
@@ -45,10 +45,6 @@ interface RioSettingsAttrs {
45
45
  fxProviders: {
46
46
  [key in FXProvider]: {
47
47
  enabled: boolean;
48
- defaultSettlementType?: {
49
- buy: EmarketsSettlementType | TransnetworkSettlementType;
50
- sell: EmarketsSettlementType | TransnetworkSettlementType;
51
- };
52
48
  };
53
49
  };
54
50
  fxTradingPolicies?: FXTradingPolicies;
@@ -134,10 +130,6 @@ interface RioSettingsDoc extends mongoose.Document {
134
130
  fxProviders: {
135
131
  [key in FXProvider]: {
136
132
  enabled: boolean;
137
- defaultSettlementType?: {
138
- buy: EmarketsSettlementType | TransnetworkSettlementType;
139
- sell: EmarketsSettlementType | TransnetworkSettlementType;
140
- };
141
133
  };
142
134
  };
143
135
  fxTradingPolicies?: FXTradingPolicies;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@riocrypto/common-server",
3
- "version": "1.0.2787",
3
+ "version": "1.0.2789",
4
4
  "description": "",
5
5
  "main": "./build/index.js",
6
6
  "types": "./build/index.d.ts",
@@ -28,7 +28,7 @@
28
28
  "@google-cloud/secret-manager": "^5.6.0",
29
29
  "@google-cloud/storage": "^7.19.0",
30
30
  "@hyperdx/node-opentelemetry": "^0.10.3",
31
- "@riocrypto/common": "1.0.2592",
31
+ "@riocrypto/common": "1.0.2595",
32
32
  "@slack/web-api": "^7.15.0",
33
33
  "@types/express": "^4.17.25",
34
34
  "axios": "1.15.2",