@morpho-dev/router 0.0.18 → 0.0.20

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.
@@ -2,9 +2,10 @@
2
2
 
3
3
  var mempool = require('@morpho-dev/mempool');
4
4
  var chains$1 = require('viem/chains');
5
+ var viem = require('viem');
5
6
  var v4 = require('zod/v4');
6
7
  var zodOpenapi = require('zod-openapi');
7
- var viem = require('viem');
8
+ var jsBase64 = require('js-base64');
8
9
 
9
10
  var __defProp = Object.defineProperty;
10
11
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
@@ -157,8 +158,6 @@ function* batch(array, batchSize) {
157
158
  yield array.slice(i, i + batchSize);
158
159
  }
159
160
  }
160
-
161
- // src/utils/cursor.ts
162
161
  function validateCursor(cursor) {
163
162
  if (!cursor || typeof cursor !== "object") {
164
163
  throw new Error("Cursor must be an object");
@@ -229,11 +228,11 @@ function validateCursor(cursor) {
229
228
  return true;
230
229
  }
231
230
  function encodeCursor(c) {
232
- return Buffer.from(JSON.stringify(c)).toString("base64url");
231
+ return jsBase64.Base64.encodeURL(JSON.stringify(c));
233
232
  }
234
233
  function decodeCursor(token) {
235
234
  if (!token) return null;
236
- const decoded = JSON.parse(Buffer.from(token, "base64url").toString());
235
+ const decoded = JSON.parse(jsBase64.Base64.decode(token));
237
236
  validateCursor(decoded);
238
237
  return decoded;
239
238
  }
@@ -345,19 +344,33 @@ var GetOffersQueryParams = v4.z.object({
345
344
  example: "1500000000000000000"
346
345
  }),
347
346
  // Time range
348
- min_maturity: v4.z.bigint({ coerce: true }).min(0n).optional().transform((val) => val === void 0 ? void 0 : Number(val)).meta({
349
- description: "Minimum maturity timestamp (Unix timestamp in seconds)",
350
- example: "1700000000"
351
- }),
352
- max_maturity: v4.z.bigint({ coerce: true }).min(0n).optional().transform((val) => val === void 0 ? void 0 : Number(val)).meta({
353
- description: "Maximum maturity timestamp (Unix timestamp in seconds)",
354
- example: "1800000000"
355
- }),
356
- min_expiry: v4.z.bigint({ coerce: true }).min(0n).optional().transform((val) => val === void 0 ? void 0 : Number(val)).meta({
347
+ min_maturity: v4.z.coerce.number().int().positive().transform((maturity, ctx) => {
348
+ try {
349
+ return mempool.Maturity.from(maturity);
350
+ } catch (e) {
351
+ ctx.addIssue({
352
+ code: "custom",
353
+ message: e.message
354
+ });
355
+ return v4.z.NEVER;
356
+ }
357
+ }).optional(),
358
+ max_maturity: v4.z.coerce.number().int().positive().transform((maturity, ctx) => {
359
+ try {
360
+ return mempool.Maturity.from(maturity);
361
+ } catch (e) {
362
+ ctx.addIssue({
363
+ code: "custom",
364
+ message: e.message
365
+ });
366
+ return v4.z.NEVER;
367
+ }
368
+ }).optional(),
369
+ min_expiry: v4.z.coerce.number().int().optional().meta({
357
370
  description: "Minimum expiry timestamp (Unix timestamp in seconds)",
358
371
  example: "1700000000"
359
372
  }),
360
- max_expiry: v4.z.bigint({ coerce: true }).min(0n).optional().transform((val) => val === void 0 ? void 0 : Number(val)).meta({
373
+ max_expiry: v4.z.coerce.number().int().optional().meta({
361
374
  description: "Maximum expiry timestamp (Unix timestamp in seconds)",
362
375
  example: "1800000000"
363
376
  }),
@@ -379,51 +392,81 @@ var GetOffersQueryParams = v4.z.object({
379
392
  {
380
393
  message: "Collateral tuple must be in format: asset:oracle:lltv#asset2:oracle2:lltv2. Oracle and lltv are optional. Asset must be 0x + 40 hex chars, oracle must be 0x + 40 hex chars, lltv must be a number (e.g., 80.5)."
381
394
  }
382
- ).transform((val) => {
395
+ ).transform((val, ctx) => {
383
396
  return val.split("#").map((tuple) => {
384
397
  const parts = tuple.split(":");
385
398
  if (parts.length === 0 || !parts[0]) {
386
- throw new v4.z.ZodError([
387
- {
388
- code: "custom",
389
- message: "Asset address is required for each collateral tuple",
390
- path: ["collateral_tuple"],
391
- input: val
392
- }
393
- ]);
399
+ ctx.addIssue({
400
+ code: "custom",
401
+ message: "Asset address is required for each collateral tuple",
402
+ path: ["asset"],
403
+ input: val
404
+ });
405
+ return v4.z.NEVER;
394
406
  }
395
407
  const asset = parts[0]?.toLowerCase();
396
408
  const oracle = parts[1]?.toLowerCase();
397
409
  const lltv = parts[2] ? parseFloat(parts[2]) : void 0;
398
410
  if (lltv !== void 0 && (lltv < MIN_LLTV || lltv > MAX_LLTV)) {
399
- throw new v4.z.ZodError([
400
- {
411
+ ctx.addIssue({
412
+ code: "custom",
413
+ message: `LLTV must be between ${MIN_LLTV} and ${MAX_LLTV} (0-100%)`,
414
+ path: ["lltv"],
415
+ input: val
416
+ });
417
+ return v4.z.NEVER;
418
+ }
419
+ let lltvValue;
420
+ if (lltv !== void 0) {
421
+ try {
422
+ lltvValue = mempool.LLTV.from(viem.parseUnits(lltv.toString(), 16));
423
+ } catch (e) {
424
+ ctx.issues.push({
401
425
  code: "custom",
402
- message: `LLTV must be between ${MIN_LLTV} and ${MAX_LLTV} (0-100%)`,
403
- path: ["collateral_tuple"],
404
- input: val
405
- }
406
- ]);
426
+ message: e instanceof mempool.LLTV.InvalidLLTVError || e instanceof mempool.LLTV.InvalidOptionError ? e.message : "Invalid LLTV.",
427
+ input: lltv,
428
+ path: ["lltv"]
429
+ });
430
+ return v4.z.NEVER;
431
+ }
407
432
  }
408
433
  return {
409
434
  asset,
410
435
  oracle,
411
- lltv
436
+ lltv: lltvValue
412
437
  };
413
438
  });
414
439
  }).optional().meta({
415
440
  description: "Filter by collateral combinations in format: asset:oracle:lltv#asset2:oracle2:lltv2. Oracle and lltv are optional. Use # to separate multiple combinations.",
416
- example: "0x1234567890123456789012345678901234567890:0xabcdefabcdefabcdefabcdefabcdefabcdefabcd:8000#0x9876543210987654321098765432109876543210::8000"
441
+ example: "0x1234567890123456789012345678901234567890:0xabcdefabcdefabcdefabcdefabcdefabcdefabcd:86#0x9876543210987654321098765432109876543210:94.5"
417
442
  }),
418
- min_lltv: v4.z.string().regex(/^\d+(\.\d+)?$/, {
419
- message: "Min LLTV must be a valid number"
420
- }).transform((val) => parseFloat(val)).pipe(v4.z.number().min(0).max(100)).optional().meta({
443
+ min_lltv: v4.z.coerce.number().min(0, { message: "LLTV must be above 0" }).max(100, { message: "LLTV must be below 100" }).transform((lltv, ctx) => {
444
+ try {
445
+ return mempool.LLTV.from(viem.parseUnits(lltv.toString(), 16));
446
+ } catch (e) {
447
+ ctx.addIssue({
448
+ code: "custom",
449
+ message: e.message,
450
+ input: lltv
451
+ });
452
+ return v4.z.NEVER;
453
+ }
454
+ }).optional().meta({
421
455
  description: "Minimum Loan-to-Value ratio (LLTV) for collateral (percentage as decimal, e.g., 80.5 = 80.5%)",
422
456
  example: "80.5"
423
457
  }),
424
- max_lltv: v4.z.string().regex(/^\d+(\.\d+)?$/, {
425
- message: "Max LLTV must be a valid number"
426
- }).transform((val) => parseFloat(val)).pipe(v4.z.number().min(0).max(100)).optional().meta({
458
+ max_lltv: v4.z.coerce.number().min(0, { message: "LLTV must be above 0" }).max(100, { message: "LLTV must be below 100" }).transform((lltv, ctx) => {
459
+ try {
460
+ return mempool.LLTV.from(viem.parseUnits(lltv.toString(), 16));
461
+ } catch (e) {
462
+ ctx.addIssue({
463
+ code: "custom",
464
+ message: e.message,
465
+ input: lltv
466
+ });
467
+ return v4.z.NEVER;
468
+ }
469
+ }).optional().meta({
427
470
  description: "Maximum Loan-to-Value ratio (LLTV) for collateral (percentage as decimal, e.g., 95.5 = 95.5%)",
428
471
  example: "95.5"
429
472
  }),
@@ -516,68 +559,89 @@ var MatchOffersQueryParams = v4.z.object({
516
559
  }),
517
560
  // Collateral filtering
518
561
  collaterals: v4.z.string().regex(
519
- /^(0x[a-fA-F0-9]{40}:0x[a-fA-F0-9]{40}:\d+)(#0x[a-fA-F0-9]{40}:0x[a-fA-F0-9]{40}:\d+)*$/,
562
+ /^(0x[a-fA-F0-9]{40}:0x[a-fA-F0-9]{40}:[0-9]+(\.[0-9]+)?)(#0x[a-fA-F0-9]{40}:0x[a-fA-F0-9]{40}:[0-9]+(\.[0-9]+)?)*$/,
520
563
  {
521
564
  message: "Collaterals must be in format: asset:oracle:lltv#asset2:oracle2:lltv2. All fields are required for each collateral."
522
565
  }
523
- ).transform((val) => {
566
+ ).transform((val, ctx) => {
524
567
  return val.split("#").map((collateral) => {
525
568
  const parts = collateral.split(":");
526
569
  if (parts.length !== 3) {
527
- throw new v4.z.ZodError([
528
- {
529
- code: "custom",
530
- message: "Each collateral must have exactly 3 parts: asset:oracle:lltv",
531
- path: ["collaterals"],
532
- input: val
533
- }
534
- ]);
570
+ ctx.addIssue({
571
+ code: "custom",
572
+ message: "Each collateral must have exactly 3 parts: asset:oracle:lltv",
573
+ path: ["collaterals"],
574
+ input: val
575
+ });
576
+ return v4.z.NEVER;
535
577
  }
536
578
  const [asset, oracle, lltvStr] = parts;
537
579
  if (!asset || !oracle || !lltvStr) {
538
- throw new v4.z.ZodError([
539
- {
540
- code: "custom",
541
- message: "Asset, oracle, and lltv are all required for each collateral",
542
- path: ["collaterals"],
543
- input: val
544
- }
545
- ]);
580
+ ctx.addIssue({
581
+ code: "custom",
582
+ message: "Asset, oracle, and lltv are all required for each collateral",
583
+ path: ["collaterals"],
584
+ input: val
585
+ });
546
586
  }
547
- const lltv = BigInt(lltvStr);
548
- if (lltv <= 0n) {
549
- throw new v4.z.ZodError([
550
- {
587
+ let lltvValue;
588
+ if (lltvStr !== void 0) {
589
+ try {
590
+ lltvValue = mempool.LLTV.from(viem.parseUnits(lltvStr, 16));
591
+ } catch (e) {
592
+ ctx.issues.push({
551
593
  code: "custom",
552
- message: "LLTV must be a positive number",
553
- path: ["collaterals"],
554
- input: val
555
- }
556
- ]);
594
+ message: e instanceof mempool.LLTV.InvalidLLTVError || e instanceof mempool.LLTV.InvalidOptionError ? e.message : "Invalid LLTV.",
595
+ input: lltvStr,
596
+ path: ["lltv"]
597
+ });
598
+ return v4.z.NEVER;
599
+ }
557
600
  }
558
601
  return {
559
602
  asset: asset.toLowerCase(),
560
603
  oracle: oracle.toLowerCase(),
561
- lltv
604
+ lltv: lltvValue
562
605
  };
563
606
  });
564
607
  }).optional().meta({
565
608
  description: "Collateral requirements in format: asset:oracle:lltv#asset2:oracle2:lltv2. Use # to separate multiple collaterals.",
566
- example: "0x1234567890123456789012345678901234567890:0xabcdefabcdefabcdefabcdefabcdefabcdefabcd:800000000000000000#0x9876543210987654321098765432109876543210:0xfedcbafedcbafedcbafedcbafedcbafedcbafedc:900000000000000000"
609
+ example: "0x1234567890123456789012345678901234567890:0xabcdefabcdefabcdefabcdefabcdefabcdefabcd:86#0x9876543210987654321098765432109876543210:0xfedcbafedcbafedcbafedcbafedcbafedcbafedc:94.5"
567
610
  }),
568
611
  // Maturity filtering
569
- maturity: v4.z.bigint({ coerce: true }).min(0n).optional().transform((val) => val === void 0 ? void 0 : Number(val)).meta({
570
- description: "Exact maturity timestamp (Unix timestamp in seconds)",
571
- example: "1700000000"
572
- }),
573
- min_maturity: v4.z.bigint({ coerce: true }).min(0n).optional().transform((val) => val === void 0 ? void 0 : Number(val)).meta({
574
- description: "Minimum maturity timestamp (Unix timestamp in seconds, inclusive)",
575
- example: "1700000000"
576
- }),
577
- max_maturity: v4.z.bigint({ coerce: true }).min(0n).optional().transform((val) => val === void 0 ? void 0 : Number(val)).meta({
578
- description: "Maximum maturity timestamp (Unix timestamp in seconds, inclusive)",
579
- example: "1800000000"
580
- }),
612
+ maturity: v4.z.coerce.number().int().positive().transform((maturity, ctx) => {
613
+ try {
614
+ return mempool.Maturity.from(maturity);
615
+ } catch (e) {
616
+ ctx.addIssue({
617
+ code: "custom",
618
+ message: e.message
619
+ });
620
+ return v4.z.NEVER;
621
+ }
622
+ }).optional(),
623
+ min_maturity: v4.z.coerce.number().int().positive().transform((maturity, ctx) => {
624
+ try {
625
+ return mempool.Maturity.from(maturity);
626
+ } catch (e) {
627
+ ctx.addIssue({
628
+ code: "custom",
629
+ message: e.message
630
+ });
631
+ return v4.z.NEVER;
632
+ }
633
+ }).optional(),
634
+ max_maturity: v4.z.coerce.number().int().positive().transform((maturity, ctx) => {
635
+ try {
636
+ return mempool.Maturity.from(maturity);
637
+ } catch (e) {
638
+ ctx.addIssue({
639
+ code: "custom",
640
+ message: e.message
641
+ });
642
+ return v4.z.NEVER;
643
+ }
644
+ }).optional(),
581
645
  // Asset and creator filtering
582
646
  loan_token: v4.z.string().regex(/^0x[a-fA-F0-9]{40}$/, {
583
647
  message: "Loan asset must be a valid Ethereum address"
@@ -639,8 +703,10 @@ var schemas = {
639
703
  get_offers: GetOffersQueryParams,
640
704
  match_offers: MatchOffersQueryParams
641
705
  };
642
- function safeParse(action, query) {
643
- return schemas[action].safeParse(query);
706
+ function safeParse(action, query, error) {
707
+ return schemas[action].safeParse(query, {
708
+ error
709
+ });
644
710
  }
645
711
 
646
712
  // src/core/apiSchema/openapi.ts
@@ -692,7 +758,7 @@ var paths = {
692
758
  }
693
759
  }
694
760
  },
695
- "/v1/match-offers": {
761
+ "/v1/offers/match": {
696
762
  get: {
697
763
  summary: "Match offers",
698
764
  description: "Find offers that match specific criteria",
@@ -843,16 +909,16 @@ async function get(config, parameters) {
843
909
  } else if (lltv !== void 0) {
844
910
  result += `:`;
845
911
  }
846
- if (lltv !== void 0) result += `:${lltv}`;
912
+ if (lltv !== void 0) result += `:${viem.formatUnits(lltv, 16)}`;
847
913
  return result;
848
914
  }).join("#");
849
915
  url.searchParams.set("collateral_tuple", tupleStr);
850
916
  }
851
917
  if (parameters.minLltv !== void 0) {
852
- url.searchParams.set("min_lltv", parameters.minLltv.toString());
918
+ url.searchParams.set("min_lltv", viem.formatUnits(parameters.minLltv, 16));
853
919
  }
854
920
  if (parameters.maxLltv !== void 0) {
855
- url.searchParams.set("max_lltv", parameters.maxLltv.toString());
921
+ url.searchParams.set("max_lltv", viem.formatUnits(parameters.maxLltv, 16));
856
922
  }
857
923
  if (parameters.sortBy) {
858
924
  url.searchParams.set("sort_by", parameters.sortBy);
@@ -874,14 +940,14 @@ async function get(config, parameters) {
874
940
  };
875
941
  }
876
942
  async function match(config, parameters) {
877
- const url = new URL(`${config.url.toString()}v1/match-offers`);
943
+ const url = new URL(`${config.url.toString()}v1/offers/match`);
878
944
  url.searchParams.set("side", parameters.side);
879
945
  url.searchParams.set("chain_id", parameters.chainId.toString());
880
946
  if (parameters.rate !== void 0) {
881
947
  url.searchParams.set("rate", parameters.rate.toString());
882
948
  }
883
949
  if (parameters.collaterals?.length) {
884
- const collateralsStr = parameters.collaterals.map(({ asset, oracle, lltv }) => `${asset}:${oracle}:${lltv}`).join("#");
950
+ const collateralsStr = parameters.collaterals.map(({ asset, oracle, lltv }) => `${asset}:${oracle}:${viem.formatUnits(lltv, 16)}`).join("#");
885
951
  url.searchParams.set("collaterals", collateralsStr);
886
952
  }
887
953
  if (parameters.maturity !== void 0) {
@@ -919,12 +985,12 @@ async function getApi(config, url) {
919
985
  const pathname = url.pathname;
920
986
  let action;
921
987
  switch (true) {
988
+ case pathname.includes("/v1/offers/match"):
989
+ action = "match_offers";
990
+ break;
922
991
  case pathname.includes("/v1/offers"):
923
992
  action = "get_offers";
924
993
  break;
925
- case pathname.includes("/v1/match-offers"):
926
- action = "match_offers";
927
- break;
928
994
  default:
929
995
  throw new HttpGetOffersFailedError("Unknown endpoint", {
930
996
  details: `Unsupported path: ${pathname}`
@@ -1135,6 +1201,7 @@ function memory(parameters) {
1135
1201
  }
1136
1202
  creators && (creators = creators.map((c) => c.toLowerCase()));
1137
1203
  loanTokens && (loanTokens = loanTokens.map((lt) => lt.toLowerCase()));
1204
+ callbackAddresses && (callbackAddresses = callbackAddresses.map((ca) => ca.toLowerCase()));
1138
1205
  collateralAssets && (collateralAssets = collateralAssets.map((ca) => ca.toLowerCase()));
1139
1206
  collateralOracles && (collateralOracles = collateralOracles.map((co) => co.toLowerCase()));
1140
1207
  collateralTuple && (collateralTuple = collateralTuple.map((ct) => ({
@@ -1171,12 +1238,8 @@ function memory(parameters) {
1171
1238
  )
1172
1239
  )
1173
1240
  ));
1174
- minLltv && (offers = offers.filter(
1175
- (o) => o.collaterals.every((c) => c.lltv >= mempool.LLTV.from(viem.parseUnits(minLltv.toString(), 16)))
1176
- ));
1177
- maxLltv && (offers = offers.filter(
1178
- (o) => o.collaterals.every((c) => c.lltv <= mempool.LLTV.from(viem.parseUnits(maxLltv.toString(), 16)))
1179
- ));
1241
+ minLltv && (offers = offers.filter((o) => o.collaterals.every((c) => c.lltv >= minLltv)));
1242
+ maxLltv && (offers = offers.filter((o) => o.collaterals.every((c) => c.lltv <= maxLltv)));
1180
1243
  offers = offers.sort((a, b) => sort(sortBy, sortOrder, a, b));
1181
1244
  let nextCursor = null;
1182
1245
  if (offers.length > limit) {
@@ -1223,8 +1286,8 @@ function memory(parameters) {
1223
1286
  limit = 20
1224
1287
  } = params;
1225
1288
  const now = mempool.Time.now();
1226
- const buy = side !== "buy";
1227
- const sortOrder = buy ? "asc" : "desc";
1289
+ const isBuying = side === "buy";
1290
+ const sortOrder = isBuying ? "desc" : "asc";
1228
1291
  let offers = Array.from(map.values()).map((o) => ({
1229
1292
  ...o,
1230
1293
  consumed: filled.get(o.chainId)?.get(o.offering.toLowerCase())?.get(o.nonce) || 0n
@@ -1237,22 +1300,27 @@ function memory(parameters) {
1237
1300
  offers = offers.filter(
1238
1301
  (o) => sortOrder === "asc" ? o.rate >= BigInt(cursor.rate) : o.rate <= BigInt(cursor.rate)
1239
1302
  );
1240
- offers = offers.filter((o) => o.hash !== cursor.hash);
1241
1303
  }
1242
- offers = offers.filter((o) => o.buy === buy);
1304
+ offers = offers.filter((o) => o.buy === !isBuying);
1243
1305
  offers = offers.filter((o) => o.chainId === BigInt(chainId));
1244
1306
  offers = offers.filter((o) => o.expiry >= now);
1245
- rate && (offers = offers.filter((o) => buy ? o.rate >= rate : o.rate <= rate));
1307
+ rate && (offers = offers.filter((o) => isBuying ? o.rate >= rate : o.rate <= rate));
1246
1308
  collaterals.length > 0 && (offers = offers.filter(
1247
- (o) => buy ? collaterals.every((c) => {
1248
- return o.collaterals.some(
1249
- (oc) => oc.asset.toLowerCase() === c.asset.toLowerCase() && oc.oracle.toLowerCase() === c.oracle.toLowerCase() && oc.lltv === c.lltv
1250
- );
1251
- }) : o.collaterals.every((oc) => {
1252
- return collaterals.some(
1253
- (c) => oc.asset.toLowerCase() === c.asset.toLowerCase() && oc.oracle.toLowerCase() === c.oracle.toLowerCase() && oc.lltv === c.lltv
1254
- );
1255
- })
1309
+ (o) => isBuying ? (
1310
+ // when wanting to buy, sell offer collaterals ⊆ user buy collaterals
1311
+ o.collaterals.every((oc) => {
1312
+ return collaterals.some(
1313
+ (c) => oc.asset.toLowerCase() === c.asset.toLowerCase() && oc.oracle.toLowerCase() === c.oracle.toLowerCase() && oc.lltv === c.lltv
1314
+ );
1315
+ })
1316
+ ) : (
1317
+ // when wanting to sell, user sell collaterals ⊆ buy offer collaterals
1318
+ collaterals.every((c) => {
1319
+ return o.collaterals.some(
1320
+ (oc) => oc.asset.toLowerCase() === c.asset.toLowerCase() && oc.oracle.toLowerCase() === c.oracle.toLowerCase() && oc.lltv === c.lltv
1321
+ );
1322
+ })
1323
+ )
1256
1324
  ));
1257
1325
  maturity && (offers = offers.filter((o) => o.maturity === maturity));
1258
1326
  minMaturity && (offers = offers.filter((o) => o.maturity >= minMaturity));
@@ -1290,6 +1358,7 @@ function memory(parameters) {
1290
1358
  }
1291
1359
  offers = Array.from(byGroup.values());
1292
1360
  offers = offers.sort((a, b) => sort("rate", sortOrder, a, b));
1361
+ cursor && (offers = offers.filter((o) => o.hash !== cursor.hash));
1293
1362
  let nextCursor = null;
1294
1363
  if (offers.length > limit) {
1295
1364
  const last = offers[limit - 1];
@@ -1322,9 +1391,12 @@ function memory(parameters) {
1322
1391
  return deleted;
1323
1392
  },
1324
1393
  updateStatus: async (parameters2) => {
1325
- if (!map.has(parameters2.offerHash.toLowerCase())) return;
1326
- map.set(parameters2.offerHash.toLowerCase(), {
1327
- ...map.get(parameters2.offerHash.toLowerCase()),
1394
+ const key = parameters2.offerHash.toLowerCase();
1395
+ const existing = map.get(key);
1396
+ if (!existing) return;
1397
+ if (existing.status === parameters2.status) return;
1398
+ map.set(key, {
1399
+ ...existing,
1328
1400
  status: parameters2.status,
1329
1401
  metadata: parameters2.metadata
1330
1402
  });