@morpho-dev/router 0.0.17 → 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 +139 -12
- package/dist/index.browser.d.ts +139 -12
- package/dist/index.browser.js +533 -92
- package/dist/index.browser.js.map +1 -1
- package/dist/index.browser.mjs +534 -89
- package/dist/index.browser.mjs.map +1 -1
- package/dist/index.node.d.cts +132 -750
- package/dist/index.node.d.ts +132 -750
- package/dist/index.node.js +895 -1302
- package/dist/index.node.js.map +1 -1
- package/dist/index.node.mjs +894 -1291
- package/dist/index.node.mjs.map +1 -1
- package/package.json +3 -12
- package/dist/drizzle/0000_add-offers-table.sql +0 -37
- package/dist/drizzle/0001_create_offer_status_relation.sql +0 -10
- package/dist/drizzle/0002_add_created_at_in_offer_status_relation.sql +0 -3
- package/dist/drizzle/0003_add-cursor-indices-to-offers.sql +0 -6
- package/dist/drizzle/0004_offer-start.sql +0 -1
- package/dist/drizzle/0005_rename-price-token-buy.sql +0 -8
- package/dist/drizzle/0006_rename-buy.sql +0 -3
- package/dist/drizzle/0007_rename-offering.sql +0 -3
- package/dist/drizzle/0008_add-consumed-relation.sql +0 -10
- package/dist/drizzle/meta/0000_snapshot.json +0 -344
- package/dist/drizzle/meta/0001_snapshot.json +0 -426
- package/dist/drizzle/meta/0002_snapshot.json +0 -439
- package/dist/drizzle/meta/0003_snapshot.json +0 -553
- package/dist/drizzle/meta/0004_snapshot.json +0 -559
- package/dist/drizzle/meta/0005_snapshot.json +0 -559
- package/dist/drizzle/meta/0006_snapshot.json +0 -559
- package/dist/drizzle/meta/0007_snapshot.json +0 -559
- package/dist/drizzle/meta/0008_snapshot.json +0 -635
- package/dist/drizzle/meta/_journal.json +0 -69
package/dist/index.browser.js
CHANGED
|
@@ -68,7 +68,7 @@ var chains = {
|
|
|
68
68
|
}
|
|
69
69
|
};
|
|
70
70
|
|
|
71
|
-
// src/core/Client.ts
|
|
71
|
+
// src/core/router/Client.ts
|
|
72
72
|
var Client_exports = {};
|
|
73
73
|
__export(Client_exports, {
|
|
74
74
|
HttpForbiddenError: () => HttpForbiddenError,
|
|
@@ -139,6 +139,18 @@ var InvalidRouterOfferError = class extends mempool.Errors.BaseError {
|
|
|
139
139
|
}
|
|
140
140
|
};
|
|
141
141
|
|
|
142
|
+
// src/utils/index.ts
|
|
143
|
+
var utils_exports = {};
|
|
144
|
+
__export(utils_exports, {
|
|
145
|
+
batch: () => batch,
|
|
146
|
+
decodeCursor: () => decodeCursor,
|
|
147
|
+
encodeCursor: () => encodeCursor,
|
|
148
|
+
poll: () => poll,
|
|
149
|
+
retry: () => retry,
|
|
150
|
+
validateCursor: () => validateCursor,
|
|
151
|
+
wait: () => wait
|
|
152
|
+
});
|
|
153
|
+
|
|
142
154
|
// src/utils/batch.ts
|
|
143
155
|
function* batch(array, batchSize) {
|
|
144
156
|
for (let i = 0; i < array.length; i += batchSize) {
|
|
@@ -249,6 +261,20 @@ function poll(fn, { interval }) {
|
|
|
249
261
|
return unwatch;
|
|
250
262
|
}
|
|
251
263
|
|
|
264
|
+
// src/utils/retry.ts
|
|
265
|
+
var retry = async (fn, attempts = 3, delayMs = 50) => {
|
|
266
|
+
let lastErr;
|
|
267
|
+
for (let i = 0; i < attempts; i++) {
|
|
268
|
+
try {
|
|
269
|
+
return await fn();
|
|
270
|
+
} catch (err) {
|
|
271
|
+
lastErr = err;
|
|
272
|
+
if (i < attempts - 1) await new Promise((r) => setTimeout(r, delayMs));
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
throw lastErr;
|
|
276
|
+
};
|
|
277
|
+
|
|
252
278
|
// src/core/apiSchema/requests.ts
|
|
253
279
|
var MAX_LIMIT = 100;
|
|
254
280
|
var DEFAULT_LIMIT = 20;
|
|
@@ -319,19 +345,33 @@ var GetOffersQueryParams = v4.z.object({
|
|
|
319
345
|
example: "1500000000000000000"
|
|
320
346
|
}),
|
|
321
347
|
// Time range
|
|
322
|
-
min_maturity: v4.z.
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
348
|
+
min_maturity: v4.z.coerce.number().int().positive().transform((maturity, ctx) => {
|
|
349
|
+
try {
|
|
350
|
+
return mempool.Maturity.from(maturity);
|
|
351
|
+
} catch (e) {
|
|
352
|
+
ctx.addIssue({
|
|
353
|
+
code: "custom",
|
|
354
|
+
message: e.message
|
|
355
|
+
});
|
|
356
|
+
return v4.z.NEVER;
|
|
357
|
+
}
|
|
358
|
+
}).optional(),
|
|
359
|
+
max_maturity: v4.z.coerce.number().int().positive().transform((maturity, ctx) => {
|
|
360
|
+
try {
|
|
361
|
+
return mempool.Maturity.from(maturity);
|
|
362
|
+
} catch (e) {
|
|
363
|
+
ctx.addIssue({
|
|
364
|
+
code: "custom",
|
|
365
|
+
message: e.message
|
|
366
|
+
});
|
|
367
|
+
return v4.z.NEVER;
|
|
368
|
+
}
|
|
369
|
+
}).optional(),
|
|
370
|
+
min_expiry: v4.z.coerce.number().int().optional().meta({
|
|
331
371
|
description: "Minimum expiry timestamp (Unix timestamp in seconds)",
|
|
332
372
|
example: "1700000000"
|
|
333
373
|
}),
|
|
334
|
-
max_expiry: v4.z.
|
|
374
|
+
max_expiry: v4.z.coerce.number().int().optional().meta({
|
|
335
375
|
description: "Maximum expiry timestamp (Unix timestamp in seconds)",
|
|
336
376
|
example: "1800000000"
|
|
337
377
|
}),
|
|
@@ -353,51 +393,81 @@ var GetOffersQueryParams = v4.z.object({
|
|
|
353
393
|
{
|
|
354
394
|
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)."
|
|
355
395
|
}
|
|
356
|
-
).transform((val) => {
|
|
396
|
+
).transform((val, ctx) => {
|
|
357
397
|
return val.split("#").map((tuple) => {
|
|
358
398
|
const parts = tuple.split(":");
|
|
359
399
|
if (parts.length === 0 || !parts[0]) {
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
]);
|
|
400
|
+
ctx.addIssue({
|
|
401
|
+
code: "custom",
|
|
402
|
+
message: "Asset address is required for each collateral tuple",
|
|
403
|
+
path: ["asset"],
|
|
404
|
+
input: val
|
|
405
|
+
});
|
|
406
|
+
return v4.z.NEVER;
|
|
368
407
|
}
|
|
369
408
|
const asset = parts[0]?.toLowerCase();
|
|
370
409
|
const oracle = parts[1]?.toLowerCase();
|
|
371
410
|
const lltv = parts[2] ? parseFloat(parts[2]) : void 0;
|
|
372
411
|
if (lltv !== void 0 && (lltv < MIN_LLTV || lltv > MAX_LLTV)) {
|
|
373
|
-
|
|
374
|
-
|
|
412
|
+
ctx.addIssue({
|
|
413
|
+
code: "custom",
|
|
414
|
+
message: `LLTV must be between ${MIN_LLTV} and ${MAX_LLTV} (0-100%)`,
|
|
415
|
+
path: ["lltv"],
|
|
416
|
+
input: val
|
|
417
|
+
});
|
|
418
|
+
return v4.z.NEVER;
|
|
419
|
+
}
|
|
420
|
+
let lltvValue;
|
|
421
|
+
if (lltv !== void 0) {
|
|
422
|
+
try {
|
|
423
|
+
lltvValue = mempool.LLTV.from(viem.parseUnits(lltv.toString(), 16));
|
|
424
|
+
} catch (e) {
|
|
425
|
+
ctx.issues.push({
|
|
375
426
|
code: "custom",
|
|
376
|
-
message:
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
}
|
|
380
|
-
|
|
427
|
+
message: e instanceof mempool.LLTV.InvalidLLTVError || e instanceof mempool.LLTV.InvalidOptionError ? e.message : "Invalid LLTV.",
|
|
428
|
+
input: lltv,
|
|
429
|
+
path: ["lltv"]
|
|
430
|
+
});
|
|
431
|
+
return v4.z.NEVER;
|
|
432
|
+
}
|
|
381
433
|
}
|
|
382
434
|
return {
|
|
383
435
|
asset,
|
|
384
436
|
oracle,
|
|
385
|
-
lltv
|
|
437
|
+
lltv: lltvValue
|
|
386
438
|
};
|
|
387
439
|
});
|
|
388
440
|
}).optional().meta({
|
|
389
441
|
description: "Filter by collateral combinations in format: asset:oracle:lltv#asset2:oracle2:lltv2. Oracle and lltv are optional. Use # to separate multiple combinations.",
|
|
390
|
-
example: "0x1234567890123456789012345678901234567890:0xabcdefabcdefabcdefabcdefabcdefabcdefabcd:
|
|
442
|
+
example: "0x1234567890123456789012345678901234567890:0xabcdefabcdefabcdefabcdefabcdefabcdefabcd:86#0x9876543210987654321098765432109876543210:94.5"
|
|
391
443
|
}),
|
|
392
|
-
min_lltv: v4.z.
|
|
393
|
-
|
|
394
|
-
|
|
444
|
+
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) => {
|
|
445
|
+
try {
|
|
446
|
+
return mempool.LLTV.from(viem.parseUnits(lltv.toString(), 16));
|
|
447
|
+
} catch (e) {
|
|
448
|
+
ctx.addIssue({
|
|
449
|
+
code: "custom",
|
|
450
|
+
message: e.message,
|
|
451
|
+
input: lltv
|
|
452
|
+
});
|
|
453
|
+
return v4.z.NEVER;
|
|
454
|
+
}
|
|
455
|
+
}).optional().meta({
|
|
395
456
|
description: "Minimum Loan-to-Value ratio (LLTV) for collateral (percentage as decimal, e.g., 80.5 = 80.5%)",
|
|
396
457
|
example: "80.5"
|
|
397
458
|
}),
|
|
398
|
-
max_lltv: v4.z.
|
|
399
|
-
|
|
400
|
-
|
|
459
|
+
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) => {
|
|
460
|
+
try {
|
|
461
|
+
return mempool.LLTV.from(viem.parseUnits(lltv.toString(), 16));
|
|
462
|
+
} catch (e) {
|
|
463
|
+
ctx.addIssue({
|
|
464
|
+
code: "custom",
|
|
465
|
+
message: e.message,
|
|
466
|
+
input: lltv
|
|
467
|
+
});
|
|
468
|
+
return v4.z.NEVER;
|
|
469
|
+
}
|
|
470
|
+
}).optional().meta({
|
|
401
471
|
description: "Maximum Loan-to-Value ratio (LLTV) for collateral (percentage as decimal, e.g., 95.5 = 95.5%)",
|
|
402
472
|
example: "95.5"
|
|
403
473
|
}),
|
|
@@ -490,68 +560,89 @@ var MatchOffersQueryParams = v4.z.object({
|
|
|
490
560
|
}),
|
|
491
561
|
// Collateral filtering
|
|
492
562
|
collaterals: v4.z.string().regex(
|
|
493
|
-
/^(0x[a-fA-F0-9]{40}:0x[a-fA-F0-9]{40}
|
|
563
|
+
/^(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]+)?)*$/,
|
|
494
564
|
{
|
|
495
565
|
message: "Collaterals must be in format: asset:oracle:lltv#asset2:oracle2:lltv2. All fields are required for each collateral."
|
|
496
566
|
}
|
|
497
|
-
).transform((val) => {
|
|
567
|
+
).transform((val, ctx) => {
|
|
498
568
|
return val.split("#").map((collateral) => {
|
|
499
569
|
const parts = collateral.split(":");
|
|
500
570
|
if (parts.length !== 3) {
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
]);
|
|
571
|
+
ctx.addIssue({
|
|
572
|
+
code: "custom",
|
|
573
|
+
message: "Each collateral must have exactly 3 parts: asset:oracle:lltv",
|
|
574
|
+
path: ["collaterals"],
|
|
575
|
+
input: val
|
|
576
|
+
});
|
|
577
|
+
return v4.z.NEVER;
|
|
509
578
|
}
|
|
510
579
|
const [asset, oracle, lltvStr] = parts;
|
|
511
580
|
if (!asset || !oracle || !lltvStr) {
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
}
|
|
519
|
-
]);
|
|
581
|
+
ctx.addIssue({
|
|
582
|
+
code: "custom",
|
|
583
|
+
message: "Asset, oracle, and lltv are all required for each collateral",
|
|
584
|
+
path: ["collaterals"],
|
|
585
|
+
input: val
|
|
586
|
+
});
|
|
520
587
|
}
|
|
521
|
-
|
|
522
|
-
if (
|
|
523
|
-
|
|
524
|
-
|
|
588
|
+
let lltvValue;
|
|
589
|
+
if (lltvStr !== void 0) {
|
|
590
|
+
try {
|
|
591
|
+
lltvValue = mempool.LLTV.from(viem.parseUnits(lltvStr, 16));
|
|
592
|
+
} catch (e) {
|
|
593
|
+
ctx.issues.push({
|
|
525
594
|
code: "custom",
|
|
526
|
-
message:
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
}
|
|
530
|
-
|
|
595
|
+
message: e instanceof mempool.LLTV.InvalidLLTVError || e instanceof mempool.LLTV.InvalidOptionError ? e.message : "Invalid LLTV.",
|
|
596
|
+
input: lltvStr,
|
|
597
|
+
path: ["lltv"]
|
|
598
|
+
});
|
|
599
|
+
return v4.z.NEVER;
|
|
600
|
+
}
|
|
531
601
|
}
|
|
532
602
|
return {
|
|
533
603
|
asset: asset.toLowerCase(),
|
|
534
604
|
oracle: oracle.toLowerCase(),
|
|
535
|
-
lltv
|
|
605
|
+
lltv: lltvValue
|
|
536
606
|
};
|
|
537
607
|
});
|
|
538
608
|
}).optional().meta({
|
|
539
609
|
description: "Collateral requirements in format: asset:oracle:lltv#asset2:oracle2:lltv2. Use # to separate multiple collaterals.",
|
|
540
|
-
example: "0x1234567890123456789012345678901234567890:0xabcdefabcdefabcdefabcdefabcdefabcdefabcd:
|
|
610
|
+
example: "0x1234567890123456789012345678901234567890:0xabcdefabcdefabcdefabcdefabcdefabcdefabcd:86#0x9876543210987654321098765432109876543210:0xfedcbafedcbafedcbafedcbafedcbafedcbafedc:94.5"
|
|
541
611
|
}),
|
|
542
612
|
// Maturity filtering
|
|
543
|
-
maturity: v4.z.
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
613
|
+
maturity: v4.z.coerce.number().int().positive().transform((maturity, ctx) => {
|
|
614
|
+
try {
|
|
615
|
+
return mempool.Maturity.from(maturity);
|
|
616
|
+
} catch (e) {
|
|
617
|
+
ctx.addIssue({
|
|
618
|
+
code: "custom",
|
|
619
|
+
message: e.message
|
|
620
|
+
});
|
|
621
|
+
return v4.z.NEVER;
|
|
622
|
+
}
|
|
623
|
+
}).optional(),
|
|
624
|
+
min_maturity: v4.z.coerce.number().int().positive().transform((maturity, ctx) => {
|
|
625
|
+
try {
|
|
626
|
+
return mempool.Maturity.from(maturity);
|
|
627
|
+
} catch (e) {
|
|
628
|
+
ctx.addIssue({
|
|
629
|
+
code: "custom",
|
|
630
|
+
message: e.message
|
|
631
|
+
});
|
|
632
|
+
return v4.z.NEVER;
|
|
633
|
+
}
|
|
634
|
+
}).optional(),
|
|
635
|
+
max_maturity: v4.z.coerce.number().int().positive().transform((maturity, ctx) => {
|
|
636
|
+
try {
|
|
637
|
+
return mempool.Maturity.from(maturity);
|
|
638
|
+
} catch (e) {
|
|
639
|
+
ctx.addIssue({
|
|
640
|
+
code: "custom",
|
|
641
|
+
message: e.message
|
|
642
|
+
});
|
|
643
|
+
return v4.z.NEVER;
|
|
644
|
+
}
|
|
645
|
+
}).optional(),
|
|
555
646
|
// Asset and creator filtering
|
|
556
647
|
loan_token: v4.z.string().regex(/^0x[a-fA-F0-9]{40}$/, {
|
|
557
648
|
message: "Loan asset must be a valid Ethereum address"
|
|
@@ -613,8 +704,10 @@ var schemas = {
|
|
|
613
704
|
get_offers: GetOffersQueryParams,
|
|
614
705
|
match_offers: MatchOffersQueryParams
|
|
615
706
|
};
|
|
616
|
-
function safeParse(action, query) {
|
|
617
|
-
return schemas[action].safeParse(query
|
|
707
|
+
function safeParse(action, query, error) {
|
|
708
|
+
return schemas[action].safeParse(query, {
|
|
709
|
+
error
|
|
710
|
+
});
|
|
618
711
|
}
|
|
619
712
|
|
|
620
713
|
// src/core/apiSchema/openapi.ts
|
|
@@ -666,7 +759,7 @@ var paths = {
|
|
|
666
759
|
}
|
|
667
760
|
}
|
|
668
761
|
},
|
|
669
|
-
"/v1/match
|
|
762
|
+
"/v1/offers/match": {
|
|
670
763
|
get: {
|
|
671
764
|
summary: "Match offers",
|
|
672
765
|
description: "Find offers that match specific criteria",
|
|
@@ -740,7 +833,7 @@ function fromResponse(offerResponse) {
|
|
|
740
833
|
};
|
|
741
834
|
}
|
|
742
835
|
|
|
743
|
-
// src/core/Client.ts
|
|
836
|
+
// src/core/router/Client.ts
|
|
744
837
|
function connect(opts) {
|
|
745
838
|
const u = new URL(opts?.url || "https://router.morpho.dev");
|
|
746
839
|
if (u.protocol !== "http:" && u.protocol !== "https:") {
|
|
@@ -817,16 +910,16 @@ async function get(config, parameters) {
|
|
|
817
910
|
} else if (lltv !== void 0) {
|
|
818
911
|
result += `:`;
|
|
819
912
|
}
|
|
820
|
-
if (lltv !== void 0) result += `:${lltv}`;
|
|
913
|
+
if (lltv !== void 0) result += `:${viem.formatUnits(lltv, 16)}`;
|
|
821
914
|
return result;
|
|
822
915
|
}).join("#");
|
|
823
916
|
url.searchParams.set("collateral_tuple", tupleStr);
|
|
824
917
|
}
|
|
825
918
|
if (parameters.minLltv !== void 0) {
|
|
826
|
-
url.searchParams.set("min_lltv", parameters.minLltv
|
|
919
|
+
url.searchParams.set("min_lltv", viem.formatUnits(parameters.minLltv, 16));
|
|
827
920
|
}
|
|
828
921
|
if (parameters.maxLltv !== void 0) {
|
|
829
|
-
url.searchParams.set("max_lltv", parameters.maxLltv
|
|
922
|
+
url.searchParams.set("max_lltv", viem.formatUnits(parameters.maxLltv, 16));
|
|
830
923
|
}
|
|
831
924
|
if (parameters.sortBy) {
|
|
832
925
|
url.searchParams.set("sort_by", parameters.sortBy);
|
|
@@ -848,14 +941,14 @@ async function get(config, parameters) {
|
|
|
848
941
|
};
|
|
849
942
|
}
|
|
850
943
|
async function match(config, parameters) {
|
|
851
|
-
const url = new URL(`${config.url.toString()}v1/match
|
|
944
|
+
const url = new URL(`${config.url.toString()}v1/offers/match`);
|
|
852
945
|
url.searchParams.set("side", parameters.side);
|
|
853
946
|
url.searchParams.set("chain_id", parameters.chainId.toString());
|
|
854
947
|
if (parameters.rate !== void 0) {
|
|
855
948
|
url.searchParams.set("rate", parameters.rate.toString());
|
|
856
949
|
}
|
|
857
950
|
if (parameters.collaterals?.length) {
|
|
858
|
-
const collateralsStr = parameters.collaterals.map(({ asset, oracle, lltv }) => `${asset}:${oracle}:${lltv}`).join("#");
|
|
951
|
+
const collateralsStr = parameters.collaterals.map(({ asset, oracle, lltv }) => `${asset}:${oracle}:${viem.formatUnits(lltv, 16)}`).join("#");
|
|
859
952
|
url.searchParams.set("collaterals", collateralsStr);
|
|
860
953
|
}
|
|
861
954
|
if (parameters.maturity !== void 0) {
|
|
@@ -896,7 +989,7 @@ async function getApi(config, url) {
|
|
|
896
989
|
case pathname.includes("/v1/offers"):
|
|
897
990
|
action = "get_offers";
|
|
898
991
|
break;
|
|
899
|
-
case pathname.includes("/v1/match
|
|
992
|
+
case pathname.includes("/v1/offers/match"):
|
|
900
993
|
action = "match_offers";
|
|
901
994
|
break;
|
|
902
995
|
default:
|
|
@@ -970,6 +1063,358 @@ var HttpGetOffersFailedError = class extends mempool.Errors.BaseError {
|
|
|
970
1063
|
}
|
|
971
1064
|
};
|
|
972
1065
|
|
|
1066
|
+
// src/OfferStore/index.ts
|
|
1067
|
+
var OfferStore_exports = {};
|
|
1068
|
+
__export(OfferStore_exports, {
|
|
1069
|
+
memory: () => memory
|
|
1070
|
+
});
|
|
1071
|
+
function memory(parameters) {
|
|
1072
|
+
const map = parameters.offers;
|
|
1073
|
+
const filled = parameters.filled;
|
|
1074
|
+
const create = async (parameters2) => {
|
|
1075
|
+
if (map.has(parameters2.offer.hash.toLowerCase())) return parameters2.offer.hash;
|
|
1076
|
+
map.set(parameters2.offer.hash.toLowerCase(), {
|
|
1077
|
+
...parameters2.offer,
|
|
1078
|
+
status: parameters2.status,
|
|
1079
|
+
metadata: parameters2.metadata
|
|
1080
|
+
});
|
|
1081
|
+
const chainId = parameters2.offer.chainId;
|
|
1082
|
+
const address = parameters2.offer.offering.toLowerCase();
|
|
1083
|
+
const nonce = parameters2.offer.nonce;
|
|
1084
|
+
const filledForChain = filled.get(chainId) || /* @__PURE__ */ new Map();
|
|
1085
|
+
const filledForOffering = filledForChain.get(address) || /* @__PURE__ */ new Map();
|
|
1086
|
+
if (!filledForOffering.has(nonce)) filledForOffering.set(nonce, 0n);
|
|
1087
|
+
filledForChain.set(address, filledForOffering);
|
|
1088
|
+
filled.set(chainId, filledForChain);
|
|
1089
|
+
return Promise.resolve(parameters2.offer.hash);
|
|
1090
|
+
};
|
|
1091
|
+
const sort = (sortBy, sortOrder, a, b) => {
|
|
1092
|
+
sortBy = sortBy || "expiry";
|
|
1093
|
+
sortOrder = sortOrder || "desc";
|
|
1094
|
+
const sortKey = sortBy === "amount" ? "assets" : sortBy;
|
|
1095
|
+
if (a[sortKey] === b[sortKey]) {
|
|
1096
|
+
if (a.hash === b.hash) return 0;
|
|
1097
|
+
return sortOrder === "asc" ? a.hash > b.hash ? 1 : -1 : b.hash > a.hash ? 1 : -1;
|
|
1098
|
+
}
|
|
1099
|
+
switch (sortBy) {
|
|
1100
|
+
case "rate":
|
|
1101
|
+
if (a.rate === b.rate) {
|
|
1102
|
+
if (a.hash === b.hash) return 0;
|
|
1103
|
+
return sortOrder === "asc" ? a.hash > b.hash ? 1 : -1 : a.hash > b.hash ? -1 : 1;
|
|
1104
|
+
}
|
|
1105
|
+
return sortOrder === "asc" ? a.rate > b.rate ? 1 : -1 : b.rate > a.rate ? 1 : -1;
|
|
1106
|
+
case "maturity":
|
|
1107
|
+
if (a.maturity === b.maturity) {
|
|
1108
|
+
if (a.hash === b.hash) return 0;
|
|
1109
|
+
return sortOrder === "asc" ? a.hash > b.hash ? 1 : -1 : a.hash > b.hash ? -1 : 1;
|
|
1110
|
+
}
|
|
1111
|
+
return sortOrder === "asc" ? a.maturity > b.maturity ? 1 : -1 : b.maturity > a.maturity ? 1 : -1;
|
|
1112
|
+
case "expiry":
|
|
1113
|
+
if (a.expiry === b.expiry) {
|
|
1114
|
+
if (a.hash === b.hash) return 0;
|
|
1115
|
+
return sortOrder === "asc" ? a.hash > b.hash ? 1 : -1 : a.hash > b.hash ? -1 : 1;
|
|
1116
|
+
}
|
|
1117
|
+
return sortOrder === "asc" ? a.expiry > b.expiry ? 1 : -1 : b.expiry > a.expiry ? 1 : -1;
|
|
1118
|
+
case "amount":
|
|
1119
|
+
if (a.assets === b.assets) {
|
|
1120
|
+
if (a.hash === b.hash) return 0;
|
|
1121
|
+
return sortOrder === "asc" ? a.hash > b.hash ? 1 : -1 : a.hash > b.hash ? -1 : 1;
|
|
1122
|
+
}
|
|
1123
|
+
return sortOrder === "asc" ? a.assets > b.assets ? 1 : -1 : b.assets > a.assets ? 1 : -1;
|
|
1124
|
+
default:
|
|
1125
|
+
if (a.expiry === b.expiry) {
|
|
1126
|
+
if (a.hash === b.hash) return 0;
|
|
1127
|
+
return sortOrder === "asc" ? a.hash > b.hash ? 1 : -1 : a.hash > b.hash ? -1 : 1;
|
|
1128
|
+
}
|
|
1129
|
+
return sortOrder === "asc" ? a.expiry > b.expiry ? 1 : -1 : b.expiry > a.expiry ? 1 : -1;
|
|
1130
|
+
}
|
|
1131
|
+
};
|
|
1132
|
+
return {
|
|
1133
|
+
create,
|
|
1134
|
+
createMany: async (parameters2) => {
|
|
1135
|
+
return Promise.all(
|
|
1136
|
+
parameters2.map((p) => create({ offer: p.offer, status: p.status, metadata: p.metadata }))
|
|
1137
|
+
);
|
|
1138
|
+
},
|
|
1139
|
+
getAll: async (params) => {
|
|
1140
|
+
const { query } = params || {};
|
|
1141
|
+
let {
|
|
1142
|
+
creators,
|
|
1143
|
+
side,
|
|
1144
|
+
chains: chains2,
|
|
1145
|
+
loanTokens,
|
|
1146
|
+
status = ["valid"],
|
|
1147
|
+
callbackAddresses,
|
|
1148
|
+
minAmount,
|
|
1149
|
+
maxAmount,
|
|
1150
|
+
minRate,
|
|
1151
|
+
maxRate,
|
|
1152
|
+
minMaturity,
|
|
1153
|
+
maxMaturity,
|
|
1154
|
+
minExpiry,
|
|
1155
|
+
maxExpiry,
|
|
1156
|
+
collateralAssets,
|
|
1157
|
+
collateralOracles,
|
|
1158
|
+
collateralTuple,
|
|
1159
|
+
minLltv,
|
|
1160
|
+
maxLltv,
|
|
1161
|
+
sortBy = "expiry",
|
|
1162
|
+
sortOrder = "desc",
|
|
1163
|
+
cursor: queryCursor,
|
|
1164
|
+
limit = 20
|
|
1165
|
+
} = query || {};
|
|
1166
|
+
const now = mempool.Time.now();
|
|
1167
|
+
const buy = side === "buy";
|
|
1168
|
+
let offers = Array.from(map.values()).map((o) => ({
|
|
1169
|
+
...o,
|
|
1170
|
+
consumed: filled.get(o.chainId)?.get(o.offering.toLowerCase())?.get(o.nonce) || 0n
|
|
1171
|
+
})).filter((o) => o.consumed < o.assets);
|
|
1172
|
+
const cursor = decodeCursor(queryCursor);
|
|
1173
|
+
if (cursor) {
|
|
1174
|
+
if (cursor.sort !== sortBy || cursor.dir !== sortOrder) {
|
|
1175
|
+
throw new Error("Cursor does not match the current sort parameters");
|
|
1176
|
+
}
|
|
1177
|
+
switch (cursor.sort) {
|
|
1178
|
+
case "rate":
|
|
1179
|
+
offers = offers.filter(
|
|
1180
|
+
(o) => (sortOrder === "asc" ? o.rate >= BigInt(cursor.rate) : o.rate <= BigInt(cursor.rate)) && (o.rate !== BigInt(cursor.rate) || (sortOrder === "asc" ? o.hash > cursor.hash : o.hash < cursor.hash))
|
|
1181
|
+
);
|
|
1182
|
+
break;
|
|
1183
|
+
case "maturity":
|
|
1184
|
+
offers = offers.filter(
|
|
1185
|
+
(o) => (sortOrder === "asc" ? o.maturity >= BigInt(cursor.maturity) : o.maturity <= BigInt(cursor.maturity)) && (o.maturity !== mempool.Maturity.from(cursor.maturity) || (sortOrder === "asc" ? o.hash > cursor.hash : o.hash < cursor.hash))
|
|
1186
|
+
);
|
|
1187
|
+
break;
|
|
1188
|
+
case "expiry":
|
|
1189
|
+
offers = offers.filter(
|
|
1190
|
+
(o) => (sortOrder === "asc" ? o.expiry >= cursor.expiry : o.expiry <= cursor.expiry) && (o.expiry !== cursor.expiry || (sortOrder === "asc" ? o.hash > cursor.hash : o.hash < cursor.hash))
|
|
1191
|
+
);
|
|
1192
|
+
break;
|
|
1193
|
+
case "amount":
|
|
1194
|
+
offers = offers.filter(
|
|
1195
|
+
(o) => (sortOrder === "asc" ? o.assets >= BigInt(cursor.assets) : o.assets <= BigInt(cursor.assets)) && (o.assets !== BigInt(cursor.assets) || (sortOrder === "asc" ? o.hash > cursor.hash : o.hash < cursor.hash))
|
|
1196
|
+
);
|
|
1197
|
+
break;
|
|
1198
|
+
default:
|
|
1199
|
+
throw new Error("Invalid sort parameter");
|
|
1200
|
+
}
|
|
1201
|
+
offers = offers.filter((o) => o.hash !== cursor.hash);
|
|
1202
|
+
}
|
|
1203
|
+
creators && (creators = creators.map((c) => c.toLowerCase()));
|
|
1204
|
+
loanTokens && (loanTokens = loanTokens.map((lt) => lt.toLowerCase()));
|
|
1205
|
+
callbackAddresses && (callbackAddresses = callbackAddresses.map((ca) => ca.toLowerCase()));
|
|
1206
|
+
collateralAssets && (collateralAssets = collateralAssets.map((ca) => ca.toLowerCase()));
|
|
1207
|
+
collateralOracles && (collateralOracles = collateralOracles.map((co) => co.toLowerCase()));
|
|
1208
|
+
collateralTuple && (collateralTuple = collateralTuple.map((ct) => ({
|
|
1209
|
+
asset: ct.asset.toLowerCase(),
|
|
1210
|
+
oracle: ct.oracle?.toLowerCase()
|
|
1211
|
+
})));
|
|
1212
|
+
offers = offers.filter((o) => o.expiry >= now);
|
|
1213
|
+
creators && (offers = offers.filter((o) => creators.includes(o.offering.toLowerCase())));
|
|
1214
|
+
side && (offers = offers.filter((o) => o.buy === buy));
|
|
1215
|
+
chains2 && (offers = offers.filter((o) => chains2.includes(Number(o.chainId))));
|
|
1216
|
+
loanTokens && (offers = offers.filter((o) => loanTokens.includes(o.loanToken.toLowerCase())));
|
|
1217
|
+
status && (offers = offers.filter((o) => status.includes(o.status)));
|
|
1218
|
+
callbackAddresses && (offers = offers.filter(
|
|
1219
|
+
(o) => callbackAddresses.includes(o.callback.address.toLowerCase())
|
|
1220
|
+
));
|
|
1221
|
+
minAmount && (offers = offers.filter((o) => o.assets >= minAmount));
|
|
1222
|
+
maxAmount && (offers = offers.filter((o) => o.assets <= maxAmount));
|
|
1223
|
+
minRate && (offers = offers.filter((o) => o.rate >= minRate));
|
|
1224
|
+
maxRate && (offers = offers.filter((o) => o.rate <= maxRate));
|
|
1225
|
+
minMaturity && (offers = offers.filter((o) => o.maturity >= minMaturity));
|
|
1226
|
+
maxMaturity && (offers = offers.filter((o) => o.maturity <= maxMaturity));
|
|
1227
|
+
minExpiry && (offers = offers.filter((o) => o.expiry >= minExpiry));
|
|
1228
|
+
maxExpiry && (offers = offers.filter((o) => o.expiry <= maxExpiry));
|
|
1229
|
+
collateralAssets && (offers = offers.filter(
|
|
1230
|
+
(o) => o.collaterals.some((c) => collateralAssets.includes(c.asset.toLowerCase()))
|
|
1231
|
+
));
|
|
1232
|
+
collateralOracles && (offers = offers.filter(
|
|
1233
|
+
(o) => o.collaterals.some((c) => collateralOracles.includes(c.oracle.toLowerCase()))
|
|
1234
|
+
));
|
|
1235
|
+
collateralTuple && (offers = offers.filter(
|
|
1236
|
+
(o) => o.collaterals.some(
|
|
1237
|
+
(c) => collateralTuple.some(
|
|
1238
|
+
(ct) => c.asset.toLowerCase() === ct.asset.toLowerCase() && (ct.oracle ? c.oracle.toLowerCase() === ct.oracle.toLowerCase() : true) && (ct.lltv ? c.lltv === mempool.LLTV.from(BigInt(ct.lltv)) : true)
|
|
1239
|
+
)
|
|
1240
|
+
)
|
|
1241
|
+
));
|
|
1242
|
+
minLltv && (offers = offers.filter((o) => o.collaterals.every((c) => c.lltv >= minLltv)));
|
|
1243
|
+
maxLltv && (offers = offers.filter((o) => o.collaterals.every((c) => c.lltv <= maxLltv)));
|
|
1244
|
+
offers = offers.sort((a, b) => sort(sortBy, sortOrder, a, b));
|
|
1245
|
+
let nextCursor = null;
|
|
1246
|
+
if (offers.length > limit) {
|
|
1247
|
+
const last = offers[limit - 1];
|
|
1248
|
+
const base = {
|
|
1249
|
+
sort: sortBy,
|
|
1250
|
+
dir: sortOrder,
|
|
1251
|
+
hash: last.hash
|
|
1252
|
+
};
|
|
1253
|
+
switch (sortBy) {
|
|
1254
|
+
case "rate":
|
|
1255
|
+
base.rate = last.rate.toString();
|
|
1256
|
+
break;
|
|
1257
|
+
case "amount":
|
|
1258
|
+
base.assets = last.assets.toString();
|
|
1259
|
+
break;
|
|
1260
|
+
case "maturity":
|
|
1261
|
+
base.maturity = last.maturity;
|
|
1262
|
+
break;
|
|
1263
|
+
default:
|
|
1264
|
+
base.expiry = last.expiry;
|
|
1265
|
+
}
|
|
1266
|
+
nextCursor = encodeCursor(base);
|
|
1267
|
+
}
|
|
1268
|
+
offers = offers.slice(0, limit);
|
|
1269
|
+
return {
|
|
1270
|
+
offers,
|
|
1271
|
+
nextCursor
|
|
1272
|
+
};
|
|
1273
|
+
},
|
|
1274
|
+
findMatchingOffers: async (params) => {
|
|
1275
|
+
const {
|
|
1276
|
+
side,
|
|
1277
|
+
chainId,
|
|
1278
|
+
rate,
|
|
1279
|
+
collaterals = [],
|
|
1280
|
+
maturity,
|
|
1281
|
+
minMaturity,
|
|
1282
|
+
maxMaturity,
|
|
1283
|
+
loanToken,
|
|
1284
|
+
creator,
|
|
1285
|
+
status,
|
|
1286
|
+
cursor: queryCursor,
|
|
1287
|
+
limit = 20
|
|
1288
|
+
} = params;
|
|
1289
|
+
const now = mempool.Time.now();
|
|
1290
|
+
const isBuying = side === "buy";
|
|
1291
|
+
const sortOrder = isBuying ? "desc" : "asc";
|
|
1292
|
+
let offers = Array.from(map.values()).map((o) => ({
|
|
1293
|
+
...o,
|
|
1294
|
+
consumed: filled.get(o.chainId)?.get(o.offering.toLowerCase())?.get(o.nonce) || 0n
|
|
1295
|
+
})).filter((o) => o.consumed < o.assets);
|
|
1296
|
+
const cursor = decodeCursor(queryCursor);
|
|
1297
|
+
if (cursor) {
|
|
1298
|
+
if (cursor.sort !== "rate" || cursor.dir !== sortOrder) {
|
|
1299
|
+
throw new Error("Cursor does not match the current sort parameters");
|
|
1300
|
+
}
|
|
1301
|
+
offers = offers.filter(
|
|
1302
|
+
(o) => sortOrder === "asc" ? o.rate >= BigInt(cursor.rate) : o.rate <= BigInt(cursor.rate)
|
|
1303
|
+
);
|
|
1304
|
+
}
|
|
1305
|
+
offers = offers.filter((o) => o.buy === !isBuying);
|
|
1306
|
+
offers = offers.filter((o) => o.chainId === BigInt(chainId));
|
|
1307
|
+
offers = offers.filter((o) => o.expiry >= now);
|
|
1308
|
+
rate && (offers = offers.filter((o) => isBuying ? o.rate >= rate : o.rate <= rate));
|
|
1309
|
+
collaterals.length > 0 && (offers = offers.filter(
|
|
1310
|
+
(o) => isBuying ? (
|
|
1311
|
+
// when wanting to buy, sell offer collaterals ⊆ user buy collaterals
|
|
1312
|
+
o.collaterals.every((oc) => {
|
|
1313
|
+
return collaterals.some(
|
|
1314
|
+
(c) => oc.asset.toLowerCase() === c.asset.toLowerCase() && oc.oracle.toLowerCase() === c.oracle.toLowerCase() && oc.lltv === c.lltv
|
|
1315
|
+
);
|
|
1316
|
+
})
|
|
1317
|
+
) : (
|
|
1318
|
+
// when wanting to sell, user sell collaterals ⊆ buy offer collaterals
|
|
1319
|
+
collaterals.every((c) => {
|
|
1320
|
+
return o.collaterals.some(
|
|
1321
|
+
(oc) => oc.asset.toLowerCase() === c.asset.toLowerCase() && oc.oracle.toLowerCase() === c.oracle.toLowerCase() && oc.lltv === c.lltv
|
|
1322
|
+
);
|
|
1323
|
+
})
|
|
1324
|
+
)
|
|
1325
|
+
));
|
|
1326
|
+
maturity && (offers = offers.filter((o) => o.maturity === maturity));
|
|
1327
|
+
minMaturity && (offers = offers.filter((o) => o.maturity >= minMaturity));
|
|
1328
|
+
maxMaturity && (offers = offers.filter((o) => o.maturity <= maxMaturity));
|
|
1329
|
+
loanToken && (offers = offers.filter((o) => o.loanToken.toLowerCase() === loanToken.toLowerCase()));
|
|
1330
|
+
creator && (offers = offers.filter((o) => o.offering.toLowerCase() === creator.toLowerCase()));
|
|
1331
|
+
status && (offers = offers.filter((o) => status.includes(o.status)));
|
|
1332
|
+
const byGroup = /* @__PURE__ */ new Map();
|
|
1333
|
+
for (const offer of offers) {
|
|
1334
|
+
const groupKey = `${offer.chainId}-${offer.offering.toLowerCase()}-${offer.nonce}-${offer.buy}`;
|
|
1335
|
+
const current = byGroup.get(groupKey);
|
|
1336
|
+
if (!current) {
|
|
1337
|
+
byGroup.set(groupKey, offer);
|
|
1338
|
+
continue;
|
|
1339
|
+
}
|
|
1340
|
+
const remainingCandidate = offer.assets - offer.consumed;
|
|
1341
|
+
const remainingCurrent = current.assets - current.consumed;
|
|
1342
|
+
let candidateIsBetter = false;
|
|
1343
|
+
if (offer.buy) {
|
|
1344
|
+
if (offer.rate !== current.rate) candidateIsBetter = offer.rate < current.rate;
|
|
1345
|
+
else if (remainingCandidate !== remainingCurrent)
|
|
1346
|
+
candidateIsBetter = remainingCandidate > remainingCurrent;
|
|
1347
|
+
else if (offer.maturity !== current.maturity)
|
|
1348
|
+
candidateIsBetter = offer.maturity > current.maturity;
|
|
1349
|
+
else candidateIsBetter = offer.hash < current.hash;
|
|
1350
|
+
} else {
|
|
1351
|
+
if (offer.rate !== current.rate) candidateIsBetter = offer.rate > current.rate;
|
|
1352
|
+
else if (remainingCandidate !== remainingCurrent)
|
|
1353
|
+
candidateIsBetter = remainingCandidate > remainingCurrent;
|
|
1354
|
+
else if (offer.maturity !== current.maturity)
|
|
1355
|
+
candidateIsBetter = offer.maturity > current.maturity;
|
|
1356
|
+
else candidateIsBetter = offer.hash < current.hash;
|
|
1357
|
+
}
|
|
1358
|
+
if (candidateIsBetter) byGroup.set(groupKey, offer);
|
|
1359
|
+
}
|
|
1360
|
+
offers = Array.from(byGroup.values());
|
|
1361
|
+
offers = offers.sort((a, b) => sort("rate", sortOrder, a, b));
|
|
1362
|
+
cursor && (offers = offers.filter((o) => o.hash !== cursor.hash));
|
|
1363
|
+
let nextCursor = null;
|
|
1364
|
+
if (offers.length > limit) {
|
|
1365
|
+
const last = offers[limit - 1];
|
|
1366
|
+
nextCursor = encodeCursor({
|
|
1367
|
+
sort: "rate",
|
|
1368
|
+
dir: sortOrder,
|
|
1369
|
+
hash: last.hash,
|
|
1370
|
+
rate: last.rate.toString()
|
|
1371
|
+
});
|
|
1372
|
+
}
|
|
1373
|
+
offers = offers.slice(0, limit);
|
|
1374
|
+
return {
|
|
1375
|
+
offers,
|
|
1376
|
+
nextCursor
|
|
1377
|
+
};
|
|
1378
|
+
},
|
|
1379
|
+
delete: async (hash) => {
|
|
1380
|
+
if (!map.has(hash.toLowerCase())) return false;
|
|
1381
|
+
map.delete(hash.toLowerCase());
|
|
1382
|
+
return true;
|
|
1383
|
+
},
|
|
1384
|
+
deleteMany: async (hashes) => {
|
|
1385
|
+
let deleted = 0;
|
|
1386
|
+
for (const hash of hashes) {
|
|
1387
|
+
if (map.has(hash.toLowerCase())) {
|
|
1388
|
+
map.delete(hash.toLowerCase());
|
|
1389
|
+
deleted++;
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1392
|
+
return deleted;
|
|
1393
|
+
},
|
|
1394
|
+
updateStatus: async (parameters2) => {
|
|
1395
|
+
const key = parameters2.offerHash.toLowerCase();
|
|
1396
|
+
const existing = map.get(key);
|
|
1397
|
+
if (!existing) return;
|
|
1398
|
+
if (existing.status === parameters2.status) return;
|
|
1399
|
+
map.set(key, {
|
|
1400
|
+
...existing,
|
|
1401
|
+
status: parameters2.status,
|
|
1402
|
+
metadata: parameters2.metadata
|
|
1403
|
+
});
|
|
1404
|
+
},
|
|
1405
|
+
updateConsumedAmount: async (parameters2) => {
|
|
1406
|
+
const chainId = parameters2.chainId;
|
|
1407
|
+
const address = parameters2.offering.toLowerCase();
|
|
1408
|
+
const nonce = parameters2.nonce;
|
|
1409
|
+
const filledForChain = filled.get(chainId) || /* @__PURE__ */ new Map();
|
|
1410
|
+
const filledForOffering = filledForChain.get(address) || /* @__PURE__ */ new Map();
|
|
1411
|
+
filledForOffering.set(nonce, parameters2.consumed);
|
|
1412
|
+
filledForChain.set(address, filledForOffering);
|
|
1413
|
+
filled.set(chainId, filledForChain);
|
|
1414
|
+
}
|
|
1415
|
+
};
|
|
1416
|
+
}
|
|
1417
|
+
|
|
973
1418
|
// src/RouterEvent.ts
|
|
974
1419
|
var RouterEvent_exports = {};
|
|
975
1420
|
__export(RouterEvent_exports, {
|
|
@@ -1205,17 +1650,13 @@ function morpho(parameters) {
|
|
|
1205
1650
|
}
|
|
1206
1651
|
|
|
1207
1652
|
exports.Chain = Chain_exports;
|
|
1653
|
+
exports.OfferStore = OfferStore_exports;
|
|
1208
1654
|
exports.Router = Client_exports;
|
|
1209
1655
|
exports.RouterEvent = RouterEvent_exports;
|
|
1210
1656
|
exports.RouterOffer = RouterOffer_exports;
|
|
1657
|
+
exports.Utils = utils_exports;
|
|
1211
1658
|
exports.Validation = Validation_exports;
|
|
1212
1659
|
exports.ValidationRule = ValidationRule_exports;
|
|
1213
|
-
exports.batch = batch;
|
|
1214
|
-
exports.decodeCursor = decodeCursor;
|
|
1215
|
-
exports.encodeCursor = encodeCursor;
|
|
1216
|
-
exports.poll = poll;
|
|
1217
|
-
exports.validateCursor = validateCursor;
|
|
1218
|
-
exports.wait = wait;
|
|
1219
1660
|
Object.keys(mempool).forEach(function (k) {
|
|
1220
1661
|
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
1221
1662
|
enumerable: true,
|