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