@riocrypto/common-server 1.0.2928 → 1.0.2930

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.
@@ -36,7 +36,6 @@ const excludedStatuses = Object.values(common_1.OrderStatus).filter((status) =>
36
36
  statusLower === "refundcomplete" ||
37
37
  statusLower.includes("failed"));
38
38
  });
39
- const HEX_DIGITS = "0123456789abcdef";
40
39
  // Every window of `length` hex characters in the text, lowercase and in the
41
40
  // order they appear. A reference has to be a run of hex, so anything else in
42
41
  // the concepto is a boundary rather than a candidate.
@@ -50,10 +49,6 @@ const hexWindows = (text, length) => {
50
49
  }
51
50
  return Array.from(windows);
52
51
  };
53
- // A concepto is short, so a bound this size is never reached by a real payment.
54
- // It is here so that a pathological text cannot turn the old-format fallback
55
- // into a query with tens of thousands of keys.
56
- const MAX_OLD_FORMAT_WINDOWS = 24;
57
52
  const getOrderFromReference = (reference, mongoose) => __awaiter(void 0, void 0, void 0, function* () {
58
53
  var _a, e_1, _b, _c;
59
54
  if (!reference) {
@@ -64,6 +59,13 @@ const getOrderFromReference = (reference, mongoose) => __awaiter(void 0, void 0,
64
59
  // New format, exact and indexed. The stored reference is what the customer was
65
60
  // shown, upper case, so the windows are compared the same way.
66
61
  const newFormatCandidates = hexWindows(reference, NEW_FORMAT_LENGTH).map((window) => window.toUpperCase());
62
+ const oldFormatWindows = hexWindows(reference, OLD_FORMAT_LENGTH);
63
+ // A reference is a run of hex, so text without one cannot contain any order's
64
+ // token in either format. Static references (SPR…) and free text end here
65
+ // instead of walking the active orders to confirm what is already known.
66
+ if (!newFormatCandidates.length && !oldFormatWindows.length) {
67
+ throw new Error("Order not found");
68
+ }
67
69
  if (newFormatCandidates.length) {
68
70
  const order = yield Order.findOne({
69
71
  "paymentInstructions.reference": { $in: newFormatCandidates },
@@ -73,36 +75,38 @@ const getOrderFromReference = (reference, mongoose) => __awaiter(void 0, void 0,
73
75
  return order;
74
76
  }
75
77
  }
76
- const oldFormatWindows = hexWindows(reference, OLD_FORMAT_LENGTH).slice(0, MAX_OLD_FORMAT_WINDOWS);
77
- // Buy orders that were never given a stored reference, from before the bank
78
- // payment listener wrote one. Only these are still compared against the id in
79
- // code. Walked once, with a cursor over a bounded query rather than paging
80
- // through every active order with skip, and before the old-format lookup so a
81
- // full match here still beats a six-character one anywhere, as it always has.
78
+ // The indexed lookup missed, so the token is compared against each active buy
79
+ // order's id the way it always was. This still catches an order whose stored
80
+ // reference is not its own token, such as one paid through a bulk, and one
81
+ // that was never given a stored reference at all. It runs only on a miss, so a
82
+ // burst of valid payments never reaches it, and it is a cursor with an _id
83
+ // projection rather than skip pagination over the same set. Placed before the
84
+ // old-format lookup so a full match here still beats a six-character one
85
+ // anywhere, as it always has.
82
86
  const newFormatWindowSet = new Set(newFormatCandidates.map((candidate) => candidate.toLowerCase()));
83
87
  const oldFormatWindowSet = new Set(oldFormatWindows);
84
- let legacyOldFormatMatchId = null;
85
- const legacyOrders = Order.find({
88
+ let scannedOldFormatMatchId = null;
89
+ const activeBuyOrders = Order.find({
86
90
  status: activeStatus,
87
91
  side: common_1.Side.Buy,
88
- "paymentInstructions.reference": { $exists: false },
89
92
  })
90
93
  .select("_id")
91
94
  .lean()
92
95
  .cursor();
93
96
  try {
94
- for (var _d = true, legacyOrders_1 = __asyncValues(legacyOrders), legacyOrders_1_1; legacyOrders_1_1 = yield legacyOrders_1.next(), _a = legacyOrders_1_1.done, !_a;) {
95
- _c = legacyOrders_1_1.value;
97
+ for (var _d = true, activeBuyOrders_1 = __asyncValues(activeBuyOrders), activeBuyOrders_1_1; activeBuyOrders_1_1 = yield activeBuyOrders_1.next(), _a = activeBuyOrders_1_1.done, !_a;) {
98
+ _c = activeBuyOrders_1_1.value;
96
99
  _d = false;
97
100
  try {
98
- const legacy = _c;
99
- const orderId = legacy._id.toString().toLowerCase();
101
+ const candidate = _c;
102
+ const orderId = candidate._id.toString().toLowerCase();
100
103
  const reference8Chars = orderId.slice(8, 10) + orderId.slice(-6);
101
104
  if (newFormatWindowSet.has(reference8Chars)) {
102
- return Order.findById(legacy._id);
105
+ return Order.findById(candidate._id);
103
106
  }
104
- if (!legacyOldFormatMatchId && oldFormatWindowSet.has(orderId.slice(-6))) {
105
- legacyOldFormatMatchId = legacy._id;
107
+ if (!scannedOldFormatMatchId &&
108
+ oldFormatWindowSet.has(orderId.slice(-6))) {
109
+ scannedOldFormatMatchId = candidate._id;
106
110
  }
107
111
  }
108
112
  finally {
@@ -113,34 +117,15 @@ const getOrderFromReference = (reference, mongoose) => __awaiter(void 0, void 0,
113
117
  catch (e_1_1) { e_1 = { error: e_1_1 }; }
114
118
  finally {
115
119
  try {
116
- if (!_d && !_a && (_b = legacyOrders_1.return)) yield _b.call(legacyOrders_1);
120
+ if (!_d && !_a && (_b = activeBuyOrders_1.return)) yield _b.call(activeBuyOrders_1);
117
121
  }
118
122
  finally { if (e_1) throw e_1.error; }
119
123
  }
120
- // Old format: the payer typed only the last six characters. Those are also the
121
- // last six of a stored new-format reference, so each six-character window is
122
- // widened to every two-character prefix it could sit behind and looked up on
123
- // the same index. 256 keys per window keeps this a point lookup rather than a
124
- // scan, which a regex with a leading wildcard could not be.
125
- if (oldFormatWindows.length) {
126
- const oldFormatCandidates = [];
127
- for (const window of oldFormatWindows) {
128
- for (const first of HEX_DIGITS) {
129
- for (const second of HEX_DIGITS) {
130
- oldFormatCandidates.push((first + second + window).toUpperCase());
131
- }
132
- }
133
- }
134
- const order = yield Order.findOne({
135
- "paymentInstructions.reference": { $in: oldFormatCandidates },
136
- status: activeStatus,
137
- }).sort({ createdAt: 1 });
138
- if (order) {
139
- return order;
140
- }
141
- }
142
- if (legacyOldFormatMatchId) {
143
- return Order.findById(legacyOldFormatMatchId);
124
+ // Old format: the payer typed only the last six characters, and the scan above
125
+ // found an order ending in them. Used only once no order anywhere matched the
126
+ // full token.
127
+ if (scannedOldFormatMatchId) {
128
+ return Order.findById(scannedOldFormatMatchId);
144
129
  }
145
130
  throw new Error("Order not found");
146
131
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@riocrypto/common-server",
3
- "version": "1.0.2928",
3
+ "version": "1.0.2930",
4
4
  "description": "",
5
5
  "main": "./build/index.js",
6
6
  "types": "./build/index.d.ts",