@morpho-dev/router 0.8.0 → 0.9.0
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/cli.js +574 -244
- package/dist/drizzle/migrations/0026_add-receiver-if-maker-is-seller.sql +1 -0
- package/dist/drizzle/migrations/meta/0026_snapshot.json +1454 -0
- package/dist/drizzle/migrations/meta/_journal.json +7 -0
- package/dist/evm/bytecode/morpho.txt +1 -1
- package/dist/index.browser.d.mts +105 -46
- package/dist/index.browser.d.mts.map +1 -1
- package/dist/index.browser.d.ts +105 -46
- package/dist/index.browser.d.ts.map +1 -1
- package/dist/index.browser.js +147 -51
- package/dist/index.browser.js.map +1 -1
- package/dist/index.browser.mjs +147 -51
- package/dist/index.browser.mjs.map +1 -1
- package/dist/index.node.d.mts +165 -56
- package/dist/index.node.d.mts.map +1 -1
- package/dist/index.node.d.ts +165 -56
- package/dist/index.node.d.ts.map +1 -1
- package/dist/index.node.js +583 -245
- package/dist/index.node.js.map +1 -1
- package/dist/index.node.mjs +584 -246
- package/dist/index.node.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.node.js
CHANGED
|
@@ -608,7 +608,7 @@ var utils_exports = /* @__PURE__ */ __exportAll({
|
|
|
608
608
|
|
|
609
609
|
//#endregion
|
|
610
610
|
//#region src/indexer/collectors/Admin.ts
|
|
611
|
-
function create$
|
|
611
|
+
function create$21(parameters) {
|
|
612
612
|
const collector = "admin";
|
|
613
613
|
const { client, db, options: { maxBatchSize = 25, maxBlockNumber } = {} } = parameters;
|
|
614
614
|
const maxBlockNumberBI = maxBlockNumber !== void 0 ? BigInt(maxBlockNumber) : void 0;
|
|
@@ -848,8 +848,8 @@ const names = [
|
|
|
848
848
|
"positions",
|
|
849
849
|
"prices"
|
|
850
850
|
];
|
|
851
|
-
function create$
|
|
852
|
-
const admin = create$
|
|
851
|
+
function create$20({ name, collect, client, db, options }) {
|
|
852
|
+
const admin = create$21({
|
|
853
853
|
client,
|
|
854
854
|
db,
|
|
855
855
|
options
|
|
@@ -1015,18 +1015,18 @@ const MorphoV2 = (0, viem.parseAbi)([
|
|
|
1015
1015
|
"function setFeeSetter(address newFeeSetter)",
|
|
1016
1016
|
"function setObligationTradingFee(bytes32 id, uint256 index, uint256 newTradingFee)",
|
|
1017
1017
|
"function setOwner(address newOwner)",
|
|
1018
|
-
"function setTradingFeeRecipient(address
|
|
1018
|
+
"function setTradingFeeRecipient(address feeRecipient)",
|
|
1019
1019
|
"function sharesOf(bytes32 id, address user) view returns (uint256)",
|
|
1020
1020
|
"function shuffleSession()",
|
|
1021
1021
|
"function supplyCollateral((address loanToken, (address token, uint256 lltv, address oracle)[] collaterals, uint256 maturity) obligation, address collateral, uint256 assets, address onBehalf)",
|
|
1022
|
-
"function take(uint256 buyerAssets, uint256 sellerAssets, uint256 obligationUnits, uint256 obligationShares, address taker, ((address loanToken, (address token, uint256 lltv, address oracle)[] collaterals, uint256 maturity) obligation, bool buy, address maker, uint256 assets, uint256 obligationUnits, uint256 obligationShares, uint256 start, uint256 expiry, uint256 tick, bytes32 group, bytes32 session, address callback, bytes callbackData) offer, (uint8 v, bytes32 r, bytes32 s) sig, bytes32 root, bytes32[] proof
|
|
1022
|
+
"function take(uint256 buyerAssets, uint256 sellerAssets, uint256 obligationUnits, uint256 obligationShares, address taker, address takerCallback, bytes takerCallbackData, address receiverIfTakerIsSeller, ((address loanToken, (address token, uint256 lltv, address oracle)[] collaterals, uint256 maturity) obligation, bool buy, address maker, uint256 assets, uint256 obligationUnits, uint256 obligationShares, uint256 start, uint256 expiry, uint256 tick, bytes32 group, bytes32 session, address callback, bytes callbackData, address receiverIfMakerIsSeller) offer, (uint8 v, bytes32 r, bytes32 s) sig, bytes32 root, bytes32[] proof) returns (uint256, uint256, uint256, uint256)",
|
|
1023
1023
|
"function totalShares(bytes32 id) view returns (uint256)",
|
|
1024
1024
|
"function totalUnits(bytes32 id) view returns (uint256)",
|
|
1025
1025
|
"function touchObligation((address loanToken, (address token, uint256 lltv, address oracle)[] collaterals, uint256 maturity) obligation) returns (bytes32)",
|
|
1026
1026
|
"function tradingFee(bytes32 id, uint256 timeToMaturity) view returns (uint256)",
|
|
1027
1027
|
"function tradingFeeRecipient() view returns (address)",
|
|
1028
|
-
"function withdraw((address loanToken, (address token, uint256 lltv, address oracle)[] collaterals, uint256 maturity) obligation, uint256 obligationUnits, uint256 shares, address onBehalf) returns (uint256, uint256)",
|
|
1029
|
-
"function withdrawCollateral((address loanToken, (address token, uint256 lltv, address oracle)[] collaterals, uint256 maturity) obligation, address collateral, uint256 assets, address onBehalf)",
|
|
1028
|
+
"function withdraw((address loanToken, (address token, uint256 lltv, address oracle)[] collaterals, uint256 maturity) obligation, uint256 obligationUnits, uint256 shares, address onBehalf, address receiver) returns (uint256, uint256)",
|
|
1029
|
+
"function withdrawCollateral((address loanToken, (address token, uint256 lltv, address oracle)[] collaterals, uint256 maturity) obligation, address collateral, uint256 assets, address onBehalf, address receiver)",
|
|
1030
1030
|
"function withdrawable(bytes32 id) view returns (uint256)",
|
|
1031
1031
|
"event Constructor(address indexed owner)",
|
|
1032
1032
|
"event Consume(address indexed user, bytes32 indexed group, uint256 amount)",
|
|
@@ -1038,12 +1038,12 @@ const MorphoV2 = (0, viem.parseAbi)([
|
|
|
1038
1038
|
"event SetFeeSetter(address indexed feeSetter)",
|
|
1039
1039
|
"event SetObligationTradingFee(bytes32 indexed id, uint256 indexed index, uint256 newTradingFee)",
|
|
1040
1040
|
"event SetOwner(address indexed owner)",
|
|
1041
|
-
"event SetTradingFeeRecipient(address indexed
|
|
1041
|
+
"event SetTradingFeeRecipient(address indexed feeRecipient)",
|
|
1042
1042
|
"event ShuffleSession(address indexed user, bytes32 session)",
|
|
1043
1043
|
"event SupplyCollateral(address caller, bytes32 indexed id, address indexed collateral, uint256 assets, address indexed onBehalf)",
|
|
1044
|
-
"event Take(address caller, bytes32 indexed id, address indexed maker, address indexed taker, bool offerIsBuy, uint256 buyerAssets, uint256 sellerAssets, uint256 obligationUnits, uint256 obligationShares, bool buyerIsLender, bool sellerIsBorrower, bytes32 group, uint256 consumed)",
|
|
1045
|
-
"event Withdraw(address
|
|
1046
|
-
"event WithdrawCollateral(address caller, bytes32 indexed id, address indexed collateral, uint256 assets, address indexed onBehalf)"
|
|
1044
|
+
"event Take(address caller, bytes32 indexed id, address indexed maker, address indexed taker, bool offerIsBuy, uint256 buyerAssets, uint256 sellerAssets, uint256 obligationUnits, uint256 obligationShares, bool buyerIsLender, bool sellerIsBorrower, address sellerReceiver, bytes32 group, uint256 consumed)",
|
|
1045
|
+
"event Withdraw(address caller, bytes32 indexed id, uint256 obligationUnits, uint256 shares, address indexed onBehalf, address indexed receiver)",
|
|
1046
|
+
"event WithdrawCollateral(address caller, bytes32 indexed id, address indexed collateral, uint256 assets, address indexed onBehalf, address receiver)"
|
|
1047
1047
|
]);
|
|
1048
1048
|
|
|
1049
1049
|
//#endregion
|
|
@@ -1315,8 +1315,8 @@ const chains$2 = {
|
|
|
1315
1315
|
name: "ethereum-virtual-testnet",
|
|
1316
1316
|
custom: {
|
|
1317
1317
|
morpho: {
|
|
1318
|
-
address: "
|
|
1319
|
-
blockCreated:
|
|
1318
|
+
address: "0xc9f3c65996fc46b9500608b2c9a9152c01c540f7",
|
|
1319
|
+
blockCreated: 23226871
|
|
1320
1320
|
},
|
|
1321
1321
|
morphoBlue: {
|
|
1322
1322
|
address: "0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb",
|
|
@@ -1462,13 +1462,13 @@ var MissingBlockNumberError = class extends BaseError {
|
|
|
1462
1462
|
|
|
1463
1463
|
//#endregion
|
|
1464
1464
|
//#region src/core/ChainRegistry.ts
|
|
1465
|
-
var ChainRegistry_exports = /* @__PURE__ */ __exportAll({ create: () => create$
|
|
1465
|
+
var ChainRegistry_exports = /* @__PURE__ */ __exportAll({ create: () => create$19 });
|
|
1466
1466
|
/**
|
|
1467
1467
|
* Creates a chain registry from a list of chains.
|
|
1468
1468
|
* @param chains - Array of chain objects to register.
|
|
1469
1469
|
* @returns A registry for looking up chains by ID. {@link ChainRegistry}
|
|
1470
1470
|
*/
|
|
1471
|
-
function create$
|
|
1471
|
+
function create$19(chains) {
|
|
1472
1472
|
const byId = /* @__PURE__ */ new Map();
|
|
1473
1473
|
for (const chain of chains) byId.set(chain.id, chain);
|
|
1474
1474
|
return {
|
|
@@ -2143,7 +2143,8 @@ const OfferSchema = () => {
|
|
|
2143
2143
|
callback: zod.object({
|
|
2144
2144
|
address: zod.string().transform(transformAddress),
|
|
2145
2145
|
data: zod.string().transform(transformHex)
|
|
2146
|
-
})
|
|
2146
|
+
}),
|
|
2147
|
+
receiverIfMakerIsSeller: zod.string().transform(transformAddress)
|
|
2147
2148
|
}).refine((data) => data.start < data.expiry, {
|
|
2148
2149
|
message: "start must be before expiry",
|
|
2149
2150
|
path: ["start"]
|
|
@@ -2159,8 +2160,12 @@ const OfferSchema = () => {
|
|
|
2159
2160
|
* @returns The created offer.
|
|
2160
2161
|
*/
|
|
2161
2162
|
function from$14(input) {
|
|
2163
|
+
const normalizedInput = {
|
|
2164
|
+
...input,
|
|
2165
|
+
receiverIfMakerIsSeller: input.receiverIfMakerIsSeller ?? input.maker
|
|
2166
|
+
};
|
|
2162
2167
|
try {
|
|
2163
|
-
return OfferSchema().parse(
|
|
2168
|
+
return OfferSchema().parse(normalizedInput);
|
|
2164
2169
|
} catch (error) {
|
|
2165
2170
|
throw new InvalidOfferError(error);
|
|
2166
2171
|
}
|
|
@@ -2212,6 +2217,7 @@ const serialize = (offer) => ({
|
|
|
2212
2217
|
address: offer.callback.address,
|
|
2213
2218
|
data: offer.callback.data
|
|
2214
2219
|
},
|
|
2220
|
+
receiverIfMakerIsSeller: offer.receiverIfMakerIsSeller,
|
|
2215
2221
|
hash: hash(offer)
|
|
2216
2222
|
});
|
|
2217
2223
|
/**
|
|
@@ -2254,8 +2260,9 @@ function random$1(config) {
|
|
|
2254
2260
|
address: viem.zeroAddress,
|
|
2255
2261
|
data: "0x"
|
|
2256
2262
|
};
|
|
2263
|
+
const maker = config?.maker ?? address();
|
|
2257
2264
|
return from$14({
|
|
2258
|
-
maker
|
|
2265
|
+
maker,
|
|
2259
2266
|
assets: assetsScaled,
|
|
2260
2267
|
obligationUnits: config?.obligationUnits ?? 0n,
|
|
2261
2268
|
obligationShares: config?.obligationShares ?? 0n,
|
|
@@ -2272,7 +2279,8 @@ function random$1(config) {
|
|
|
2272
2279
|
...random$3(),
|
|
2273
2280
|
lltv
|
|
2274
2281
|
})).sort((a, b) => a.asset.localeCompare(b.asset)),
|
|
2275
|
-
callback: config?.callback ?? emptyCallback
|
|
2282
|
+
callback: config?.callback ?? emptyCallback,
|
|
2283
|
+
receiverIfMakerIsSeller: config?.receiverIfMakerIsSeller ?? maker
|
|
2276
2284
|
});
|
|
2277
2285
|
}
|
|
2278
2286
|
const weightedChoice = (pairs) => {
|
|
@@ -2358,6 +2366,10 @@ const types = {
|
|
|
2358
2366
|
{
|
|
2359
2367
|
name: "callback",
|
|
2360
2368
|
type: "Callback"
|
|
2369
|
+
},
|
|
2370
|
+
{
|
|
2371
|
+
name: "receiverIfMakerIsSeller",
|
|
2372
|
+
type: "address"
|
|
2361
2373
|
}
|
|
2362
2374
|
],
|
|
2363
2375
|
Collateral: [
|
|
@@ -2403,7 +2415,8 @@ function hash(offer) {
|
|
|
2403
2415
|
callback: {
|
|
2404
2416
|
address: offer.callback.address.toLowerCase(),
|
|
2405
2417
|
data: offer.callback.data
|
|
2406
|
-
}
|
|
2418
|
+
},
|
|
2419
|
+
receiverIfMakerIsSeller: offer.receiverIfMakerIsSeller.toLowerCase()
|
|
2407
2420
|
},
|
|
2408
2421
|
primaryType: "Offer",
|
|
2409
2422
|
types
|
|
@@ -2506,6 +2519,10 @@ const OfferAbi = [
|
|
|
2506
2519
|
name: "data",
|
|
2507
2520
|
type: "bytes"
|
|
2508
2521
|
}]
|
|
2522
|
+
},
|
|
2523
|
+
{
|
|
2524
|
+
name: "receiverIfMakerIsSeller",
|
|
2525
|
+
type: "address"
|
|
2509
2526
|
}
|
|
2510
2527
|
];
|
|
2511
2528
|
function encode$1(offer) {
|
|
@@ -2524,7 +2541,8 @@ function encode$1(offer) {
|
|
|
2524
2541
|
offer.loanToken,
|
|
2525
2542
|
BigInt(offer.start),
|
|
2526
2543
|
offer.collaterals,
|
|
2527
|
-
offer.callback
|
|
2544
|
+
offer.callback,
|
|
2545
|
+
offer.receiverIfMakerIsSeller
|
|
2528
2546
|
]);
|
|
2529
2547
|
}
|
|
2530
2548
|
function decode$1(data) {
|
|
@@ -2558,7 +2576,8 @@ function decode$1(data) {
|
|
|
2558
2576
|
callback: {
|
|
2559
2577
|
address: decoded[14].address,
|
|
2560
2578
|
data: decoded[14].data
|
|
2561
|
-
}
|
|
2579
|
+
},
|
|
2580
|
+
receiverIfMakerIsSeller: decoded[15]
|
|
2562
2581
|
});
|
|
2563
2582
|
}
|
|
2564
2583
|
/**
|
|
@@ -2634,6 +2653,12 @@ const takeEvent = {
|
|
|
2634
2653
|
indexed: false,
|
|
2635
2654
|
internalType: "bool"
|
|
2636
2655
|
},
|
|
2656
|
+
{
|
|
2657
|
+
name: "sellerReceiver",
|
|
2658
|
+
type: "address",
|
|
2659
|
+
indexed: false,
|
|
2660
|
+
internalType: "address"
|
|
2661
|
+
},
|
|
2637
2662
|
{
|
|
2638
2663
|
name: "group",
|
|
2639
2664
|
type: "bytes32",
|
|
@@ -2819,76 +2844,6 @@ function from$12(parameters) {
|
|
|
2819
2844
|
};
|
|
2820
2845
|
}
|
|
2821
2846
|
|
|
2822
|
-
//#endregion
|
|
2823
|
-
//#region src/core/Quote.ts
|
|
2824
|
-
var Quote_exports = /* @__PURE__ */ __exportAll({
|
|
2825
|
-
InvalidQuoteError: () => InvalidQuoteError,
|
|
2826
|
-
QuoteSchema: () => QuoteSchema,
|
|
2827
|
-
from: () => from$11,
|
|
2828
|
-
fromSnakeCase: () => fromSnakeCase,
|
|
2829
|
-
random: () => random
|
|
2830
|
-
});
|
|
2831
|
-
const QuoteSchema = zod.object({
|
|
2832
|
-
obligationId: zod.string().transform(transformHex),
|
|
2833
|
-
ask: zod.object({ price: zod.bigint({ coerce: true }).min(0n).max(viem.maxUint256) }),
|
|
2834
|
-
bid: zod.object({ price: zod.bigint({ coerce: true }).min(0n).max(viem.maxUint256) })
|
|
2835
|
-
});
|
|
2836
|
-
/**
|
|
2837
|
-
* Creates a quote for a given obligation.
|
|
2838
|
-
* @constructor
|
|
2839
|
-
* @param parameters - {@link from.Parameters}
|
|
2840
|
-
* @returns The created quote. {@link Quote}
|
|
2841
|
-
* @throws If the quote is invalid. {@link InvalidQuoteError}
|
|
2842
|
-
*
|
|
2843
|
-
* @example
|
|
2844
|
-
* ```ts
|
|
2845
|
-
* const quote = Quote.from({ obligationId: "0x123", ask: { price: 100n }, bid: { price: 100n } });
|
|
2846
|
-
* ```
|
|
2847
|
-
*/
|
|
2848
|
-
function from$11(parameters) {
|
|
2849
|
-
try {
|
|
2850
|
-
const parsedQuote = QuoteSchema.parse(parameters);
|
|
2851
|
-
return {
|
|
2852
|
-
obligationId: parsedQuote.obligationId,
|
|
2853
|
-
ask: parsedQuote.ask,
|
|
2854
|
-
bid: parsedQuote.bid
|
|
2855
|
-
};
|
|
2856
|
-
} catch (error) {
|
|
2857
|
-
throw new InvalidQuoteError(error);
|
|
2858
|
-
}
|
|
2859
|
-
}
|
|
2860
|
-
/**
|
|
2861
|
-
* Creates a quote from a snake case object.
|
|
2862
|
-
* @throws If the quote is invalid. {@link InvalidQuoteError}
|
|
2863
|
-
* @param snake - {@link fromSnakeCase.Parameters}
|
|
2864
|
-
* @returns The created quote. {@link fromSnakeCase.ReturnType}
|
|
2865
|
-
*/
|
|
2866
|
-
function fromSnakeCase(snake) {
|
|
2867
|
-
return from$11(fromSnakeCase$3(snake));
|
|
2868
|
-
}
|
|
2869
|
-
/**
|
|
2870
|
-
* Generates a random quote.
|
|
2871
|
-
* @returns A randomly generated quote. {@link random.ReturnType}
|
|
2872
|
-
*
|
|
2873
|
-
* @example
|
|
2874
|
-
* ```ts
|
|
2875
|
-
* const quote = Quote.random();
|
|
2876
|
-
* ```
|
|
2877
|
-
*/
|
|
2878
|
-
function random() {
|
|
2879
|
-
return from$11({
|
|
2880
|
-
obligationId: id(random$2()),
|
|
2881
|
-
ask: { price: BigInt(int(1e6)) },
|
|
2882
|
-
bid: { price: BigInt(int(1e6)) }
|
|
2883
|
-
});
|
|
2884
|
-
}
|
|
2885
|
-
var InvalidQuoteError = class extends BaseError {
|
|
2886
|
-
name = "Quote.InvalidQuoteError";
|
|
2887
|
-
constructor(error) {
|
|
2888
|
-
super("Invalid quote.", { cause: error });
|
|
2889
|
-
}
|
|
2890
|
-
};
|
|
2891
|
-
|
|
2892
2847
|
//#endregion
|
|
2893
2848
|
//#region src/core/Tick.ts
|
|
2894
2849
|
var Tick_exports = /* @__PURE__ */ __exportAll({
|
|
@@ -2968,6 +2923,82 @@ var InvalidPriceError = class extends BaseError {
|
|
|
2968
2923
|
}
|
|
2969
2924
|
};
|
|
2970
2925
|
|
|
2926
|
+
//#endregion
|
|
2927
|
+
//#region src/core/Quote.ts
|
|
2928
|
+
var Quote_exports = /* @__PURE__ */ __exportAll({
|
|
2929
|
+
InvalidQuoteError: () => InvalidQuoteError,
|
|
2930
|
+
from: () => from$11,
|
|
2931
|
+
fromSnakeCase: () => fromSnakeCase,
|
|
2932
|
+
random: () => random
|
|
2933
|
+
});
|
|
2934
|
+
const SideInputSchema = zod.object({ tick: zod.number().int().min(0).max(TICK_RANGE).nullable() }).strict();
|
|
2935
|
+
const QuoteInputSchema = zod.object({
|
|
2936
|
+
obligationId: zod.string().transform(transformHex),
|
|
2937
|
+
ask: SideInputSchema,
|
|
2938
|
+
bid: SideInputSchema
|
|
2939
|
+
}).strict();
|
|
2940
|
+
/**
|
|
2941
|
+
* Creates a quote for a given obligation.
|
|
2942
|
+
* @constructor
|
|
2943
|
+
* @param parameters - {@link from.Parameters}
|
|
2944
|
+
* @returns The created quote. {@link Quote}
|
|
2945
|
+
* @throws If the quote is invalid. {@link InvalidQuoteError}
|
|
2946
|
+
*
|
|
2947
|
+
* @example
|
|
2948
|
+
* ```ts
|
|
2949
|
+
* const quote = Quote.from({ obligationId: "0x123", ask: { tick: 500 }, bid: { tick: 510 } });
|
|
2950
|
+
* ```
|
|
2951
|
+
*/
|
|
2952
|
+
function from$11(parameters) {
|
|
2953
|
+
try {
|
|
2954
|
+
const parsedQuote = QuoteInputSchema.parse(parameters);
|
|
2955
|
+
return {
|
|
2956
|
+
obligationId: parsedQuote.obligationId,
|
|
2957
|
+
ask: sideFromTick(parsedQuote.ask),
|
|
2958
|
+
bid: sideFromTick(parsedQuote.bid)
|
|
2959
|
+
};
|
|
2960
|
+
} catch (error) {
|
|
2961
|
+
throw new InvalidQuoteError(error);
|
|
2962
|
+
}
|
|
2963
|
+
}
|
|
2964
|
+
/**
|
|
2965
|
+
* Creates a quote from a snake case object.
|
|
2966
|
+
* @throws If the quote is invalid. {@link InvalidQuoteError}
|
|
2967
|
+
* @param snake - {@link fromSnakeCase.Parameters}
|
|
2968
|
+
* @returns The created quote. {@link fromSnakeCase.ReturnType}
|
|
2969
|
+
*/
|
|
2970
|
+
function fromSnakeCase(snake) {
|
|
2971
|
+
return from$11(fromSnakeCase$3(snake));
|
|
2972
|
+
}
|
|
2973
|
+
/**
|
|
2974
|
+
* Generates a random quote.
|
|
2975
|
+
* @returns A randomly generated quote. {@link random.ReturnType}
|
|
2976
|
+
*
|
|
2977
|
+
* @example
|
|
2978
|
+
* ```ts
|
|
2979
|
+
* const quote = Quote.random();
|
|
2980
|
+
* ```
|
|
2981
|
+
*/
|
|
2982
|
+
function random() {
|
|
2983
|
+
return from$11({
|
|
2984
|
+
obligationId: id(random$2()),
|
|
2985
|
+
ask: { tick: int(TICK_RANGE + 1) },
|
|
2986
|
+
bid: { tick: int(TICK_RANGE + 1) }
|
|
2987
|
+
});
|
|
2988
|
+
}
|
|
2989
|
+
var InvalidQuoteError = class extends BaseError {
|
|
2990
|
+
name = "Quote.InvalidQuoteError";
|
|
2991
|
+
constructor(error) {
|
|
2992
|
+
super("Invalid quote.", { cause: error });
|
|
2993
|
+
}
|
|
2994
|
+
};
|
|
2995
|
+
function sideFromTick(side) {
|
|
2996
|
+
return {
|
|
2997
|
+
tick: side.tick,
|
|
2998
|
+
price: side.tick === null ? 0n : tickToPrice(side.tick)
|
|
2999
|
+
};
|
|
3000
|
+
}
|
|
3001
|
+
|
|
2971
3002
|
//#endregion
|
|
2972
3003
|
//#region src/core/TradingFee.ts
|
|
2973
3004
|
var TradingFee_exports = /* @__PURE__ */ __exportAll({
|
|
@@ -3644,6 +3675,7 @@ const offers = s.table(EnumTableName.OFFERS, {
|
|
|
3644
3675
|
buy: (0, drizzle_orm_pg_core.boolean)("buy").notNull(),
|
|
3645
3676
|
callbackAddress: (0, drizzle_orm_pg_core.varchar)("callback_address", { length: 42 }).notNull(),
|
|
3646
3677
|
callbackData: (0, drizzle_orm_pg_core.text)("callback_data").notNull(),
|
|
3678
|
+
receiverIfMakerIsSeller: (0, drizzle_orm_pg_core.varchar)("receiver_if_maker_is_seller", { length: 42 }),
|
|
3647
3679
|
blockNumber: (0, drizzle_orm_pg_core.bigint)("block_number", { mode: "number" }).notNull(),
|
|
3648
3680
|
updatedAt: (0, drizzle_orm_pg_core.timestamp)("updated_at").defaultNow().notNull()
|
|
3649
3681
|
}, (table) => [
|
|
@@ -5025,7 +5057,7 @@ async function* collectPrices(parameters) {
|
|
|
5025
5057
|
//#region src/indexer/collectors/CollectorBuilder.ts
|
|
5026
5058
|
function createBuilder(parameters) {
|
|
5027
5059
|
const { client, db, gatekeeper, options: { maxBlockNumber, blockWindow, interval } = {} } = parameters;
|
|
5028
|
-
const createCollector = (name, collect) => create$
|
|
5060
|
+
const createCollector = (name, collect) => create$20({
|
|
5029
5061
|
name,
|
|
5030
5062
|
collect,
|
|
5031
5063
|
client,
|
|
@@ -5117,7 +5149,7 @@ const from$7 = (parameters) => {
|
|
|
5117
5149
|
//#endregion
|
|
5118
5150
|
//#region src/indexer/Indexer.ts
|
|
5119
5151
|
var Indexer_exports = /* @__PURE__ */ __exportAll({
|
|
5120
|
-
create: () => create$
|
|
5152
|
+
create: () => create$18,
|
|
5121
5153
|
from: () => from$6
|
|
5122
5154
|
});
|
|
5123
5155
|
function from$6(config) {
|
|
@@ -5133,7 +5165,7 @@ function from$6(config) {
|
|
|
5133
5165
|
retryAttempts,
|
|
5134
5166
|
retryDelayMs
|
|
5135
5167
|
});
|
|
5136
|
-
return create$
|
|
5168
|
+
return create$18({
|
|
5137
5169
|
client,
|
|
5138
5170
|
collectors: [
|
|
5139
5171
|
offersCollector,
|
|
@@ -5143,7 +5175,7 @@ function from$6(config) {
|
|
|
5143
5175
|
]
|
|
5144
5176
|
});
|
|
5145
5177
|
}
|
|
5146
|
-
function create$
|
|
5178
|
+
function create$18(params) {
|
|
5147
5179
|
const { collectors, client } = params;
|
|
5148
5180
|
const indexerId = `${client.chain.id.toString()}.indexer`;
|
|
5149
5181
|
const tracer = getTracer(`router.${indexerId}`);
|
|
@@ -5172,12 +5204,12 @@ function create$17(params) {
|
|
|
5172
5204
|
|
|
5173
5205
|
//#endregion
|
|
5174
5206
|
//#region src/api/Health.ts
|
|
5175
|
-
var Health_exports = /* @__PURE__ */ __exportAll({ create: () => create$
|
|
5207
|
+
var Health_exports = /* @__PURE__ */ __exportAll({ create: () => create$17 });
|
|
5176
5208
|
const DEFAULT_MAX_ALLOWED_LAG = 5;
|
|
5177
5209
|
/**
|
|
5178
5210
|
* Create a health service that exposes collector and chain block numbers.
|
|
5179
5211
|
*/
|
|
5180
|
-
function create$
|
|
5212
|
+
function create$17(parameters) {
|
|
5181
5213
|
const { db, maxAllowedLag = DEFAULT_MAX_ALLOWED_LAG, healthClients, chainRegistry } = parameters;
|
|
5182
5214
|
const loadSnapshot = async () => {
|
|
5183
5215
|
const [collectorRows, chainRows, remoteBlockByChainId] = await Promise.all([
|
|
@@ -5341,6 +5373,7 @@ var ObligationResponse_exports = /* @__PURE__ */ __exportAll({ from: () => from$
|
|
|
5341
5373
|
* Creates an `ObligationResponse` from a `Obligation`.
|
|
5342
5374
|
* @constructor
|
|
5343
5375
|
* @param obligation - {@link Obligation}
|
|
5376
|
+
* @param quote - {@link Quote}
|
|
5344
5377
|
* @returns The created `ObligationResponse`. {@link ObligationResponse}
|
|
5345
5378
|
*/
|
|
5346
5379
|
function from$4(obligation, quote) {
|
|
@@ -5354,8 +5387,14 @@ function from$4(obligation, quote) {
|
|
|
5354
5387
|
oracle: c.oracle
|
|
5355
5388
|
})),
|
|
5356
5389
|
maturity: obligation.maturity,
|
|
5357
|
-
ask: {
|
|
5358
|
-
|
|
5390
|
+
ask: {
|
|
5391
|
+
tick: quote.ask.tick,
|
|
5392
|
+
price: quote.ask.price.toString()
|
|
5393
|
+
},
|
|
5394
|
+
bid: {
|
|
5395
|
+
tick: quote.bid.tick,
|
|
5396
|
+
price: quote.bid.price.toString()
|
|
5397
|
+
}
|
|
5359
5398
|
};
|
|
5360
5399
|
}
|
|
5361
5400
|
|
|
@@ -5403,7 +5442,8 @@ function from$3(input) {
|
|
|
5403
5442
|
group: input.group,
|
|
5404
5443
|
session: input.session,
|
|
5405
5444
|
callback: input.callback.address,
|
|
5406
|
-
callback_data: input.callback.data
|
|
5445
|
+
callback_data: input.callback.data,
|
|
5446
|
+
receiver_if_maker_is_seller: input.receiverIfMakerIsSeller
|
|
5407
5447
|
},
|
|
5408
5448
|
offer_hash: input.hash,
|
|
5409
5449
|
obligation_id: id({
|
|
@@ -5470,7 +5510,7 @@ var InternalServerError = class extends APIError {
|
|
|
5470
5510
|
super(STATUS_CODE.INTERNAL_SERVER_ERROR, message, "INTERNAL_SERVER_ERROR");
|
|
5471
5511
|
}
|
|
5472
5512
|
};
|
|
5473
|
-
var BadRequestError = class extends APIError {
|
|
5513
|
+
var BadRequestError$1 = class extends APIError {
|
|
5474
5514
|
constructor(message = "Invalid JSON format", details) {
|
|
5475
5515
|
super(STATUS_CODE.BAD_REQUEST, message, "BAD_REQUEST", details);
|
|
5476
5516
|
}
|
|
@@ -5492,7 +5532,7 @@ function success(args) {
|
|
|
5492
5532
|
*/
|
|
5493
5533
|
function failure(err) {
|
|
5494
5534
|
if (err instanceof APIError) return handleAPIError(err);
|
|
5495
|
-
if (err instanceof SyntaxError) return handleAPIError(new BadRequestError(err.message));
|
|
5535
|
+
if (err instanceof SyntaxError) return handleAPIError(new BadRequestError$1(err.message));
|
|
5496
5536
|
if (err instanceof zod.ZodError) return handleAPIError(handleZodError(err));
|
|
5497
5537
|
return handleAPIError(new InternalServerError());
|
|
5498
5538
|
}
|
|
@@ -5542,7 +5582,7 @@ function __decorate(decorators, target, key, desc) {
|
|
|
5542
5582
|
//#region src/api/Schema/openapi.ts
|
|
5543
5583
|
const timestampExample = "2024-01-01T12:00:00.000Z";
|
|
5544
5584
|
const offerCursorExample = "eyJvZmZzZXQiOjEwMH0";
|
|
5545
|
-
const obligationCursorExample = "
|
|
5585
|
+
const obligationCursorExample = "eyJzb3J0IjpbImlkIl0sImlkIjoiMHgxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAiLCJhc2siOiIwIiwiYmlkIjoiMCIsIm1hdHVyaXR5IjoxNzYxOTIyODAwfQ";
|
|
5546
5586
|
const offerExample = {
|
|
5547
5587
|
offer: {
|
|
5548
5588
|
obligation: {
|
|
@@ -5565,7 +5605,8 @@ const offerExample = {
|
|
|
5565
5605
|
group: "0x000000000000000000000000000000000000000000000000000000000008b8f4",
|
|
5566
5606
|
session: "0x0000000000000000000000000000000000000000000000000000000000000000",
|
|
5567
5607
|
callback: "0x0000000000000000000000000000000000000000",
|
|
5568
|
-
callback_data: "0x"
|
|
5608
|
+
callback_data: "0x",
|
|
5609
|
+
receiver_if_maker_is_seller: "0x7b093658BE7f90B63D7c359e8f408e503c2D9401"
|
|
5569
5610
|
},
|
|
5570
5611
|
offer_hash: "0xac4bd8318ec914f89f8af913f162230575b0ac0696a19256bc12138c5cfe1427",
|
|
5571
5612
|
obligation_id: "0x25690ae1aee324a005be565f3bcdd16dbf8daf7969b26c181c8b8f467dad9abc",
|
|
@@ -5619,7 +5660,8 @@ const validateOfferExample = {
|
|
|
5619
5660
|
callback: {
|
|
5620
5661
|
address: "0x0000000000000000000000000000000000000000",
|
|
5621
5662
|
data: "0x"
|
|
5622
|
-
}
|
|
5663
|
+
},
|
|
5664
|
+
receiver_if_maker_is_seller: "0x7b093658BE7f90B63D7c359e8f408e503c2D9401"
|
|
5623
5665
|
};
|
|
5624
5666
|
const routerStatusExample = {
|
|
5625
5667
|
status: "live",
|
|
@@ -5690,11 +5732,23 @@ __decorate([(0, openapi_metadata_decorators.ApiProperty)({
|
|
|
5690
5732
|
example: validateOfferExample.callback.data
|
|
5691
5733
|
})], ValidateCallbackRequest.prototype, "data", void 0);
|
|
5692
5734
|
var AskResponse = class {};
|
|
5735
|
+
__decorate([(0, openapi_metadata_decorators.ApiProperty)({
|
|
5736
|
+
type: "number",
|
|
5737
|
+
nullable: true,
|
|
5738
|
+
example: 500,
|
|
5739
|
+
description: "Best ask tick. Null when there is no active ask quote."
|
|
5740
|
+
})], AskResponse.prototype, "tick", void 0);
|
|
5693
5741
|
__decorate([(0, openapi_metadata_decorators.ApiProperty)({
|
|
5694
5742
|
type: "string",
|
|
5695
5743
|
example: "1000000000000000000"
|
|
5696
5744
|
})], AskResponse.prototype, "price", void 0);
|
|
5697
5745
|
var BidResponse = class {};
|
|
5746
|
+
__decorate([(0, openapi_metadata_decorators.ApiProperty)({
|
|
5747
|
+
type: "number",
|
|
5748
|
+
nullable: true,
|
|
5749
|
+
example: 500,
|
|
5750
|
+
description: "Best bid tick. Null when there is no active bid quote."
|
|
5751
|
+
})], BidResponse.prototype, "tick", void 0);
|
|
5698
5752
|
__decorate([(0, openapi_metadata_decorators.ApiProperty)({
|
|
5699
5753
|
type: "string",
|
|
5700
5754
|
example: "1000000000000000000"
|
|
@@ -5767,6 +5821,10 @@ __decorate([(0, openapi_metadata_decorators.ApiProperty)({
|
|
|
5767
5821
|
type: "string",
|
|
5768
5822
|
example: offerExample.offer.callback_data
|
|
5769
5823
|
})], OfferDataResponse.prototype, "callback_data", void 0);
|
|
5824
|
+
__decorate([(0, openapi_metadata_decorators.ApiProperty)({
|
|
5825
|
+
type: "string",
|
|
5826
|
+
example: offerExample.offer.receiver_if_maker_is_seller
|
|
5827
|
+
})], OfferDataResponse.prototype, "receiver_if_maker_is_seller", void 0);
|
|
5770
5828
|
var OfferListItemResponse = class {};
|
|
5771
5829
|
__decorate([(0, openapi_metadata_decorators.ApiProperty)({
|
|
5772
5830
|
type: () => OfferDataResponse,
|
|
@@ -6036,6 +6094,10 @@ __decorate([(0, openapi_metadata_decorators.ApiProperty)({
|
|
|
6036
6094
|
type: () => ValidateCallbackRequest,
|
|
6037
6095
|
example: validateOfferExample.callback
|
|
6038
6096
|
})], ValidateOfferRequest.prototype, "callback", void 0);
|
|
6097
|
+
__decorate([(0, openapi_metadata_decorators.ApiProperty)({
|
|
6098
|
+
type: "string",
|
|
6099
|
+
example: validateOfferExample.receiver_if_maker_is_seller
|
|
6100
|
+
})], ValidateOfferRequest.prototype, "receiver_if_maker_is_seller", void 0);
|
|
6039
6101
|
var ValidateOffersRequest = class {};
|
|
6040
6102
|
__decorate([(0, openapi_metadata_decorators.ApiProperty)({
|
|
6041
6103
|
type: () => [ValidateOfferRequest],
|
|
@@ -6588,13 +6650,13 @@ __decorate([
|
|
|
6588
6650
|
methods: ["get"],
|
|
6589
6651
|
path: "/v1/obligations",
|
|
6590
6652
|
summary: "List all obligations",
|
|
6591
|
-
description: "Returns a list of obligations with their current best ask and bid.
|
|
6653
|
+
description: "Returns a list of obligations with their current best ask and bid. Sorting is customizable with the sort parameter and defaults to id ascending."
|
|
6592
6654
|
}),
|
|
6593
6655
|
(0, openapi_metadata_decorators.ApiQuery)({
|
|
6594
6656
|
name: "cursor",
|
|
6595
6657
|
type: "string",
|
|
6596
6658
|
example: obligationCursorExample,
|
|
6597
|
-
description: "
|
|
6659
|
+
description: "Pagination cursor in base64url-encoded format."
|
|
6598
6660
|
}),
|
|
6599
6661
|
(0, openapi_metadata_decorators.ApiQuery)({
|
|
6600
6662
|
name: "limit",
|
|
@@ -6638,6 +6700,15 @@ __decorate([
|
|
|
6638
6700
|
style: "form",
|
|
6639
6701
|
explode: false
|
|
6640
6702
|
}),
|
|
6703
|
+
(0, openapi_metadata_decorators.ApiQuery)({
|
|
6704
|
+
name: "sort",
|
|
6705
|
+
type: "string",
|
|
6706
|
+
required: false,
|
|
6707
|
+
example: "-ask,bid,maturity",
|
|
6708
|
+
description: "Sort order as comma-separated fields (`id`, `ask`, `bid`, `maturity`). Prefix with `-` for descending order. Max 3 fields.",
|
|
6709
|
+
style: "form",
|
|
6710
|
+
explode: false
|
|
6711
|
+
}),
|
|
6641
6712
|
(0, openapi_metadata_decorators.ApiResponse)({
|
|
6642
6713
|
status: 200,
|
|
6643
6714
|
description: "Success",
|
|
@@ -6773,11 +6844,13 @@ function from$2(position) {
|
|
|
6773
6844
|
//#endregion
|
|
6774
6845
|
//#region src/api/Schema/requests.ts
|
|
6775
6846
|
const MAX_LIMIT = 100;
|
|
6776
|
-
const DEFAULT_LIMIT$
|
|
6847
|
+
const DEFAULT_LIMIT$5 = 20;
|
|
6848
|
+
const MAX_OBLIGATION_SORT_FIELDS = 3;
|
|
6777
6849
|
const CONFIG_RULES_MAX_LIMIT = 1e3;
|
|
6778
6850
|
const CONFIG_RULES_DEFAULT_LIMIT = 100;
|
|
6779
6851
|
const CONFIG_CONTRACTS_MAX_LIMIT = 1e3;
|
|
6780
6852
|
const CONFIG_CONTRACTS_DEFAULT_LIMIT = 1e3;
|
|
6853
|
+
const OBLIGATION_SORT_ENTRY_REGEX = /^-?(id|ask|bid|maturity)$/;
|
|
6781
6854
|
/** Validate cursor is a valid base64url-encoded JSON object.
|
|
6782
6855
|
* Domain layer handles semantic validation of cursor fields. */
|
|
6783
6856
|
function isValidBase64urlJson(val) {
|
|
@@ -6809,8 +6882,8 @@ const PaginationQueryParams = zod.object({
|
|
|
6809
6882
|
description: "Pagination cursor in base64url-encoded format",
|
|
6810
6883
|
example: "eyJzaWRlIjoic2VsbCIsImN1cnJlbnRQcmljZSI6IjEwMDAwMDAwMDAwMDAwMDAwMDAiLCJibG9ja051bWJlciI6MSwiYXNzZXRzIjoiMTAwMDAwMDAwMDAwMDAwMDAwMCIsImhhc2giOiIweGRmZDY4NTllM2UwODJkMTkzODlhMWFlYzFiZGFkN2U4ZDkyZDk2YjFhYTc5NDBkYTkxYTMxMjVkMzFlM2JlNWIiLCJ0b3RhbFJldHVybmVkIjoxMCwibm93IjoxNjAwMDAwMDAwfQ"
|
|
6811
6884
|
}),
|
|
6812
|
-
limit: zod.string().regex(/^[1-9]\d*$/, { message: "Limit must be a positive integer" }).transform((val) => Number.parseInt(val, 10)).pipe(zod.number().max(MAX_LIMIT, { message: `Limit cannot exceed ${MAX_LIMIT}` })).optional().default(DEFAULT_LIMIT$
|
|
6813
|
-
description: `Limit maximum: ${MAX_LIMIT}. Default: ${DEFAULT_LIMIT$
|
|
6885
|
+
limit: zod.string().regex(/^[1-9]\d*$/, { message: "Limit must be a positive integer" }).transform((val) => Number.parseInt(val, 10)).pipe(zod.number().max(MAX_LIMIT, { message: `Limit cannot exceed ${MAX_LIMIT}` })).optional().default(DEFAULT_LIMIT$5).meta({
|
|
6886
|
+
description: `Limit maximum: ${MAX_LIMIT}. Default: ${DEFAULT_LIMIT$5}`,
|
|
6814
6887
|
example: 10
|
|
6815
6888
|
})
|
|
6816
6889
|
});
|
|
@@ -6907,9 +6980,12 @@ const GetOffersQueryParams = PaginationQueryParams.omit({ cursor: true }).extend
|
|
|
6907
6980
|
});
|
|
6908
6981
|
const GetObligationsQueryParams = zod.object({
|
|
6909
6982
|
...PaginationQueryParams.shape,
|
|
6910
|
-
cursor: zod.string().optional().
|
|
6911
|
-
|
|
6912
|
-
|
|
6983
|
+
cursor: zod.string().optional().refine((val) => {
|
|
6984
|
+
if (!val) return true;
|
|
6985
|
+
return isValidBase64urlJson(val);
|
|
6986
|
+
}, { message: "Invalid cursor format. Must be a valid base64url-encoded cursor object" }).meta({
|
|
6987
|
+
description: "Pagination cursor in base64url-encoded format.",
|
|
6988
|
+
example: "eyJzb3J0IjpbImlkIl0sImlkIjoiMHgxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAiLCJhc2siOiIwIiwiYmlkIjoiMCIsIm1hdHVyaXR5IjoxNzYxOTIyODAwfQ"
|
|
6913
6989
|
}),
|
|
6914
6990
|
chains: csvArray(zod.string().regex(/^[1-9]\d*$/, { message: "Chain must be a positive integer" }).transform((val) => Number.parseInt(val, 10))).meta({
|
|
6915
6991
|
description: "Filter by chain IDs (comma-separated).",
|
|
@@ -6926,6 +7002,24 @@ const GetObligationsQueryParams = zod.object({
|
|
|
6926
7002
|
maturities: csvArray(zod.string().regex(/^[1-9]\d*$/, { message: "Maturity must be a positive integer" }).transform((val) => Number.parseInt(val, 10))).meta({
|
|
6927
7003
|
description: "Filter by exact maturity timestamps (comma-separated, unix seconds).",
|
|
6928
7004
|
example: "1761922800,1764524800"
|
|
7005
|
+
}),
|
|
7006
|
+
sort: csvArray(zod.string().regex(OBLIGATION_SORT_ENTRY_REGEX, { message: "Sort entries must be one of: id, ask, bid, maturity (optionally prefixed with '-')" })).refine((entries) => entries === void 0 || entries.length <= MAX_OBLIGATION_SORT_FIELDS, { message: `Sort cannot include more than ${MAX_OBLIGATION_SORT_FIELDS} fields` }).superRefine((entries, ctx) => {
|
|
7007
|
+
if (!entries) return;
|
|
7008
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7009
|
+
for (const entry of entries) {
|
|
7010
|
+
const field = entry.startsWith("-") ? entry.slice(1) : entry;
|
|
7011
|
+
if (seen.has(field)) {
|
|
7012
|
+
ctx.addIssue({
|
|
7013
|
+
code: "custom",
|
|
7014
|
+
message: `Duplicate sort field: ${field}`
|
|
7015
|
+
});
|
|
7016
|
+
return;
|
|
7017
|
+
}
|
|
7018
|
+
seen.add(field);
|
|
7019
|
+
}
|
|
7020
|
+
}).meta({
|
|
7021
|
+
description: "Sort order as comma-separated fields. Prefix a field with '-' for descending order. Max 3 fields.",
|
|
7022
|
+
example: "-ask,bid,maturity"
|
|
6929
7023
|
})
|
|
6930
7024
|
});
|
|
6931
7025
|
const GetObligationParams = zod.object({ obligation_id: zod.string({ error: "Obligation id is required and must be a valid 32-byte hex string" }).regex(/^0x[a-fA-F0-9]{64}$/, { error: "Obligation id must be a valid 32-byte hex string" }).transform((val) => val.toLowerCase()).meta({
|
|
@@ -6949,8 +7043,8 @@ const BookPaginationQueryParams = zod.object({
|
|
|
6949
7043
|
description: "Pagination cursor in base64url-encoded format for book levels",
|
|
6950
7044
|
example: "eyJzaWRlIjoiYnV5IiwibGFzdFJhdGUiOiIxMDAwMDAwMDAwMDAwMDAwMDAwIiwib2ZmZXJzQ3Vyc29yIjpudWxsfQ"
|
|
6951
7045
|
}),
|
|
6952
|
-
limit: zod.string().regex(/^[1-9]\d*$/, { message: "Limit must be a positive integer" }).transform((val) => Number.parseInt(val, 10)).pipe(zod.number().max(MAX_LIMIT, { message: `Limit cannot exceed ${MAX_LIMIT}` })).optional().default(DEFAULT_LIMIT$
|
|
6953
|
-
description: `Limit maximum: ${MAX_LIMIT}. Default: ${DEFAULT_LIMIT$
|
|
7046
|
+
limit: zod.string().regex(/^[1-9]\d*$/, { message: "Limit must be a positive integer" }).transform((val) => Number.parseInt(val, 10)).pipe(zod.number().max(MAX_LIMIT, { message: `Limit cannot exceed ${MAX_LIMIT}` })).optional().default(DEFAULT_LIMIT$5).meta({
|
|
7047
|
+
description: `Limit maximum: ${MAX_LIMIT}. Default: ${DEFAULT_LIMIT$5}`,
|
|
6954
7048
|
example: 10
|
|
6955
7049
|
})
|
|
6956
7050
|
});
|
|
@@ -7127,7 +7221,7 @@ async function getConfigContracts(query, chainRegistry) {
|
|
|
7127
7221
|
}
|
|
7128
7222
|
function parseCursor$1(cursor) {
|
|
7129
7223
|
const [chain, address] = cursor.split(":", 2);
|
|
7130
|
-
if (!chain || !address) throw new BadRequestError("Cursor must be in the format chain_id:0x...");
|
|
7224
|
+
if (!chain || !address) throw new BadRequestError$1("Cursor must be in the format chain_id:0x...");
|
|
7131
7225
|
return {
|
|
7132
7226
|
chain_id: Number.parseInt(chain, 10),
|
|
7133
7227
|
address: address.toLowerCase()
|
|
@@ -7253,19 +7347,19 @@ const oracles = {
|
|
|
7253
7347
|
const configs = {
|
|
7254
7348
|
ethereum: {
|
|
7255
7349
|
callbacks: [{ type: Type$1.BuyWithEmptyCallback }, { type: Type$1.SellWithEmptyCallback }],
|
|
7256
|
-
maturities: [MaturityType.
|
|
7350
|
+
maturities: [MaturityType.EndOfWeek, MaturityType.EndOfNextWeek]
|
|
7257
7351
|
},
|
|
7258
7352
|
base: {
|
|
7259
7353
|
callbacks: [{ type: Type$1.BuyWithEmptyCallback }, { type: Type$1.SellWithEmptyCallback }],
|
|
7260
|
-
maturities: [MaturityType.
|
|
7354
|
+
maturities: [MaturityType.EndOfWeek, MaturityType.EndOfNextWeek]
|
|
7261
7355
|
},
|
|
7262
7356
|
"ethereum-virtual-testnet": {
|
|
7263
7357
|
callbacks: [{ type: Type$1.BuyWithEmptyCallback }, { type: Type$1.SellWithEmptyCallback }],
|
|
7264
|
-
maturities: [MaturityType.
|
|
7358
|
+
maturities: [MaturityType.EndOfWeek, MaturityType.EndOfNextWeek]
|
|
7265
7359
|
},
|
|
7266
7360
|
anvil: {
|
|
7267
7361
|
callbacks: [{ type: Type$1.BuyWithEmptyCallback }, { type: Type$1.SellWithEmptyCallback }],
|
|
7268
|
-
maturities: [MaturityType.
|
|
7362
|
+
maturities: [MaturityType.EndOfWeek, MaturityType.EndOfNextWeek]
|
|
7269
7363
|
}
|
|
7270
7364
|
};
|
|
7271
7365
|
|
|
@@ -7380,8 +7474,8 @@ async function getConfigRules(query, chains) {
|
|
|
7380
7474
|
} catch (err) {
|
|
7381
7475
|
return failure(err);
|
|
7382
7476
|
}
|
|
7383
|
-
if (cursorRule && typeFilter && !typeFilter.has(cursorRule.type)) return failure(new BadRequestError("Cursor type must match requested rule types"));
|
|
7384
|
-
if (cursorRule && chainFilter && !chainFilter.has(cursorRule.chain_id)) return failure(new BadRequestError("Cursor chain_id must match requested chains"));
|
|
7477
|
+
if (cursorRule && typeFilter && !typeFilter.has(cursorRule.type)) return failure(new BadRequestError$1("Cursor type must match requested rule types"));
|
|
7478
|
+
if (cursorRule && chainFilter && !chainFilter.has(cursorRule.chain_id)) return failure(new BadRequestError$1("Cursor chain_id must match requested chains"));
|
|
7385
7479
|
const startIndex = cursorRule ? findStartIndex(filteredRules, cursorRule) : 0;
|
|
7386
7480
|
const page = filteredRules.slice(startIndex, startIndex + limit);
|
|
7387
7481
|
const nextCursor = startIndex + limit < filteredRules.length && page.length > 0 ? formatCursor(page.at(-1)) : null;
|
|
@@ -7401,15 +7495,15 @@ function formatCursor(rule) {
|
|
|
7401
7495
|
}
|
|
7402
7496
|
function parseCursor(cursor) {
|
|
7403
7497
|
const [type, chain, ...rest] = cursor.split(":");
|
|
7404
|
-
if (!type || !chain || rest.length === 0) throw new BadRequestError("Cursor must be in the format type:chain_id:<value>");
|
|
7405
|
-
if (!isConfigRuleType(type)) throw new BadRequestError("Cursor has an invalid rule type");
|
|
7498
|
+
if (!type || !chain || rest.length === 0) throw new BadRequestError$1("Cursor must be in the format type:chain_id:<value>");
|
|
7499
|
+
if (!isConfigRuleType(type)) throw new BadRequestError$1("Cursor has an invalid rule type");
|
|
7406
7500
|
const chain_id = Number.parseInt(chain, 10);
|
|
7407
|
-
if (!Number.isFinite(chain_id)) throw new BadRequestError("Cursor has an invalid chain_id");
|
|
7501
|
+
if (!Number.isFinite(chain_id)) throw new BadRequestError$1("Cursor has an invalid chain_id");
|
|
7408
7502
|
if (type === "maturity") {
|
|
7409
7503
|
const timestampValue = Number.parseInt(rest[0] ?? "", 10);
|
|
7410
7504
|
const nameValue = rest.slice(1).join(":");
|
|
7411
|
-
if (!Number.isFinite(timestampValue) || nameValue.length === 0) throw new BadRequestError("Cursor must be in the format maturity:chain_id:timestamp:name");
|
|
7412
|
-
if (!isMaturityType(nameValue)) throw new BadRequestError("Cursor has an invalid maturity name");
|
|
7505
|
+
if (!Number.isFinite(timestampValue) || nameValue.length === 0) throw new BadRequestError$1("Cursor must be in the format maturity:chain_id:timestamp:name");
|
|
7506
|
+
if (!isMaturityType(nameValue)) throw new BadRequestError$1("Cursor has an invalid maturity name");
|
|
7413
7507
|
return {
|
|
7414
7508
|
type,
|
|
7415
7509
|
chain_id,
|
|
@@ -7420,8 +7514,8 @@ function parseCursor(cursor) {
|
|
|
7420
7514
|
if (type === "callback") {
|
|
7421
7515
|
const callbackTypeValue = rest[0] ?? "";
|
|
7422
7516
|
const addressValue = rest.slice(1).join(":");
|
|
7423
|
-
if (!callbackTypeValue || !addressValue) throw new BadRequestError("Cursor must be in the format callback:chain_id:callback_type:address");
|
|
7424
|
-
if (!isCallbackType(callbackTypeValue)) throw new BadRequestError("Cursor has an invalid callback type");
|
|
7517
|
+
if (!callbackTypeValue || !addressValue) throw new BadRequestError$1("Cursor must be in the format callback:chain_id:callback_type:address");
|
|
7518
|
+
if (!isCallbackType(callbackTypeValue)) throw new BadRequestError$1("Cursor has an invalid callback type");
|
|
7425
7519
|
return {
|
|
7426
7520
|
type,
|
|
7427
7521
|
chain_id,
|
|
@@ -7431,14 +7525,14 @@ function parseCursor(cursor) {
|
|
|
7431
7525
|
}
|
|
7432
7526
|
if (type === "loan_token" || type === "collateral_token" || type === "oracle") {
|
|
7433
7527
|
const addressValue = rest.join(":");
|
|
7434
|
-
if (!addressValue) throw new BadRequestError(`Cursor must be in the format ${type}:chain_id:address`);
|
|
7528
|
+
if (!addressValue) throw new BadRequestError$1(`Cursor must be in the format ${type}:chain_id:address`);
|
|
7435
7529
|
return {
|
|
7436
7530
|
type,
|
|
7437
7531
|
chain_id,
|
|
7438
7532
|
address: parseAddress(addressValue, "Cursor address")
|
|
7439
7533
|
};
|
|
7440
7534
|
}
|
|
7441
|
-
throw new BadRequestError("Cursor has an invalid rule type");
|
|
7535
|
+
throw new BadRequestError$1("Cursor has an invalid rule type");
|
|
7442
7536
|
}
|
|
7443
7537
|
function findStartIndex(rules, cursor) {
|
|
7444
7538
|
let low = 0;
|
|
@@ -7452,7 +7546,7 @@ function findStartIndex(rules, cursor) {
|
|
|
7452
7546
|
return low;
|
|
7453
7547
|
}
|
|
7454
7548
|
function parseAddress(address, label) {
|
|
7455
|
-
if (!/^0x[a-fA-F0-9]{40}$/.test(address)) throw new BadRequestError(`${label} must be a valid 20-byte address`);
|
|
7549
|
+
if (!/^0x[a-fA-F0-9]{40}$/.test(address)) throw new BadRequestError$1(`${label} must be a valid 20-byte address`);
|
|
7456
7550
|
return address.toLowerCase();
|
|
7457
7551
|
}
|
|
7458
7552
|
function isConfigRuleType(value) {
|
|
@@ -7465,7 +7559,7 @@ function parseMaturity(value) {
|
|
|
7465
7559
|
try {
|
|
7466
7560
|
return from$16(value);
|
|
7467
7561
|
} catch (err) {
|
|
7468
|
-
throw new BadRequestError(err instanceof Error ? err.message : "Invalid maturity timestamp");
|
|
7562
|
+
throw new BadRequestError$1(err instanceof Error ? err.message : "Invalid maturity timestamp");
|
|
7469
7563
|
}
|
|
7470
7564
|
}
|
|
7471
7565
|
function isCallbackType(value) {
|
|
@@ -7561,7 +7655,7 @@ async function getHealth(query, db, chainRegistry) {
|
|
|
7561
7655
|
try {
|
|
7562
7656
|
const parsed = safeParse("get_health", query);
|
|
7563
7657
|
if (!parsed.success) return failure(parsed.error);
|
|
7564
|
-
const snapshot = await create$
|
|
7658
|
+
const snapshot = await create$17({
|
|
7565
7659
|
db,
|
|
7566
7660
|
chainRegistry
|
|
7567
7661
|
}).getSnapshot();
|
|
@@ -7590,7 +7684,7 @@ async function getHealthChains(query, db, healthClients, chainRegistry) {
|
|
|
7590
7684
|
try {
|
|
7591
7685
|
const parsed = safeParse("get_health_chains", query);
|
|
7592
7686
|
if (!parsed.success) return failure(parsed.error);
|
|
7593
|
-
const snapshot = await create$
|
|
7687
|
+
const snapshot = await create$17({
|
|
7594
7688
|
db,
|
|
7595
7689
|
healthClients,
|
|
7596
7690
|
chainRegistry
|
|
@@ -7622,7 +7716,7 @@ async function getHealthCollectors(query, db, chainRegistry) {
|
|
|
7622
7716
|
try {
|
|
7623
7717
|
const parsed = safeParse("get_health_collectors", query);
|
|
7624
7718
|
if (!parsed.success) return failure(parsed.error);
|
|
7625
|
-
const snapshot = await create$
|
|
7719
|
+
const snapshot = await create$17({
|
|
7626
7720
|
db,
|
|
7627
7721
|
chainRegistry
|
|
7628
7722
|
}).getSnapshot();
|
|
@@ -7651,39 +7745,274 @@ async function getHealthCollectors(query, db, chainRegistry) {
|
|
|
7651
7745
|
}
|
|
7652
7746
|
}
|
|
7653
7747
|
|
|
7748
|
+
//#endregion
|
|
7749
|
+
//#region src/database/readers/ObligationsListing.ts
|
|
7750
|
+
const SORT_FIELDS = [
|
|
7751
|
+
"id",
|
|
7752
|
+
"ask",
|
|
7753
|
+
"bid",
|
|
7754
|
+
"maturity"
|
|
7755
|
+
];
|
|
7756
|
+
const CURSOR_ID_REGEX = /^0x[a-f0-9]{64}$/i;
|
|
7757
|
+
const INT32_MIN = -2147483648;
|
|
7758
|
+
const INT32_MAX = 2147483647;
|
|
7759
|
+
const INT32_MAX_BIGINT = BigInt(INT32_MAX);
|
|
7760
|
+
const MAX_CURSOR_SORT_FIELDS = 4;
|
|
7761
|
+
const DEFAULT_LIMIT$4 = 20;
|
|
7762
|
+
var BadRequestError = class extends Error {
|
|
7763
|
+
constructor(message) {
|
|
7764
|
+
super(message);
|
|
7765
|
+
this.name = "ObligationsListingBadRequestError";
|
|
7766
|
+
}
|
|
7767
|
+
};
|
|
7768
|
+
/**
|
|
7769
|
+
* Creates the obligations listing reader facade.
|
|
7770
|
+
* @param parameters - Reader dependencies.
|
|
7771
|
+
* @returns Obligations listing reader.
|
|
7772
|
+
*/
|
|
7773
|
+
function create$16(parameters) {
|
|
7774
|
+
const { db } = parameters;
|
|
7775
|
+
return { list: async (queryParameters) => {
|
|
7776
|
+
const { ids, chainId: chainIds, loanToken: loanTokens, collateralToken: collateralTokens, maturity: maturities, sort: sortTokens, cursor: encodedCursor, limit: requestedLimit } = queryParameters ?? {};
|
|
7777
|
+
const limit = requestedLimit ?? DEFAULT_LIMIT$4;
|
|
7778
|
+
if (!Number.isInteger(limit) || limit <= 0) throw new BadRequestError("Limit must be a positive integer");
|
|
7779
|
+
const cursorPayload = encodedCursor ? decodeCursorPayload(encodedCursor) : void 0;
|
|
7780
|
+
const requestedSort = normalizeSort(sortTokens);
|
|
7781
|
+
const cursorSort = cursorPayload ? normalizeSort(cursorPayload.sort) : void 0;
|
|
7782
|
+
if (cursorSort !== void 0 && sortTokens !== void 0 && !hasSameSort(requestedSort, cursorSort)) throw new BadRequestError("Cursor sort does not match requested sort");
|
|
7783
|
+
const sort = sortTokens !== void 0 ? requestedSort : cursorSort ?? requestedSort;
|
|
7784
|
+
const cursorValues = cursorPayload ? cursorValuesFromPayload(cursorPayload) : void 0;
|
|
7785
|
+
const now$3 = now();
|
|
7786
|
+
const loanTokenFilter = loanTokens !== void 0 && loanTokens.length > 0 ? drizzle_orm.sql`(${drizzle_orm.sql.join(loanTokens.map((token) => drizzle_orm.sql`LOWER(${obligations.loanToken}) = ${token.toLowerCase()}`), drizzle_orm.sql` OR `)})` : void 0;
|
|
7787
|
+
const collateralFilter = collateralTokens !== void 0 && collateralTokens.length > 0 ? drizzle_orm.sql`EXISTS (
|
|
7788
|
+
SELECT 1 FROM ${obligationCollateralsV2} oc
|
|
7789
|
+
WHERE oc.obligation_id = ${obligations.obligationId}
|
|
7790
|
+
AND (${drizzle_orm.sql.join(collateralTokens.map((token) => drizzle_orm.sql`LOWER(oc.asset) = ${token.toLowerCase()}`), drizzle_orm.sql` OR `)})
|
|
7791
|
+
)` : void 0;
|
|
7792
|
+
const bestAskTick = db.select({ askTick: offers.tick }).from(offers).innerJoin(groups, (0, drizzle_orm.and)((0, drizzle_orm.eq)(offers.groupChainId, groups.chainId), (0, drizzle_orm.eq)(offers.groupMaker, groups.maker), (0, drizzle_orm.eq)(offers.group, groups.group))).leftJoin(validations, (0, drizzle_orm.eq)(offers.hash, validations.offerHash)).leftJoin(status, (0, drizzle_orm.eq)(validations.statusId, status.id)).where((0, drizzle_orm.and)((0, drizzle_orm.eq)(offers.obligationId, obligations.obligationId), (0, drizzle_orm.eq)(offers.buy, false), (0, drizzle_orm.gte)(offers.expiry, now$3), (0, drizzle_orm.gte)(offers.maturity, now$3), (0, drizzle_orm.lte)(offers.start, now$3), drizzle_orm.sql`(${status.code} IS NULL OR ${status.code} = ${Status.VALID})`)).orderBy((0, drizzle_orm.desc)(offers.tick)).limit(1).as("best_ask_tick");
|
|
7793
|
+
const bestBidTick = db.select({ bidTick: offers.tick }).from(offers).innerJoin(groups, (0, drizzle_orm.and)((0, drizzle_orm.eq)(offers.groupChainId, groups.chainId), (0, drizzle_orm.eq)(offers.groupMaker, groups.maker), (0, drizzle_orm.eq)(offers.group, groups.group))).leftJoin(validations, (0, drizzle_orm.eq)(offers.hash, validations.offerHash)).leftJoin(status, (0, drizzle_orm.eq)(validations.statusId, status.id)).where((0, drizzle_orm.and)((0, drizzle_orm.eq)(offers.obligationId, obligations.obligationId), (0, drizzle_orm.eq)(offers.buy, true), (0, drizzle_orm.gte)(offers.expiry, now$3), (0, drizzle_orm.gte)(offers.maturity, now$3), (0, drizzle_orm.lte)(offers.start, now$3), drizzle_orm.sql`(${status.code} IS NULL OR ${status.code} = ${Status.VALID})`)).orderBy((0, drizzle_orm.asc)(offers.tick)).limit(1).as("best_bid_tick");
|
|
7794
|
+
const obligationsWithQuotes = db.select({
|
|
7795
|
+
obligationId: obligations.obligationId,
|
|
7796
|
+
chainId: obligations.chainId,
|
|
7797
|
+
loanToken: obligations.loanToken,
|
|
7798
|
+
collaterals: drizzle_orm.sql`ARRAY_AGG(jsonb_build_object('asset', ${obligationCollateralsV2.asset}, 'oracle', ${oracles$1.address}, 'lltv', ${obligationCollateralsV2.lltv}))`.as("collaterals"),
|
|
7799
|
+
maturity: obligations.maturity,
|
|
7800
|
+
askTick: drizzle_orm.sql`MAX(${bestAskTick.askTick})`.as("ask_tick"),
|
|
7801
|
+
bidTick: drizzle_orm.sql`MAX(${bestBidTick.bidTick})`.as("bid_tick"),
|
|
7802
|
+
ask: drizzle_orm.sql`COALESCE(MAX(${bestAskTick.askTick}) + 1, 0)`.as("ask"),
|
|
7803
|
+
bid: drizzle_orm.sql`COALESCE(MAX(${bestBidTick.bidTick}) + 1, 0)`.as("bid")
|
|
7804
|
+
}).from(obligations).innerJoin(obligationCollateralsV2, (0, drizzle_orm.eq)(obligations.obligationId, obligationCollateralsV2.obligationId)).innerJoin(oracles$1, drizzle_orm.sql`${obligationCollateralsV2.oracleChainId} = ${oracles$1.chainId}
|
|
7805
|
+
AND ${obligationCollateralsV2.oracleAddress} = ${oracles$1.address}`).leftJoinLateral(bestAskTick, drizzle_orm.sql`true`).leftJoinLateral(bestBidTick, drizzle_orm.sql`true`).groupBy(obligations.obligationId).where((0, drizzle_orm.and)(ids !== void 0 && ids.length > 0 ? (0, drizzle_orm.inArray)(obligations.obligationId, ids) : void 0, chainIds !== void 0 && chainIds.length > 0 ? (0, drizzle_orm.inArray)(obligations.chainId, chainIds) : void 0, loanTokenFilter, maturities !== void 0 && maturities.length > 0 ? (0, drizzle_orm.inArray)(obligations.maturity, maturities) : (0, drizzle_orm.gte)(obligations.maturity, now$3), collateralFilter)).as("obligations_with_quotes");
|
|
7806
|
+
const sortColumns = {
|
|
7807
|
+
id: obligationsWithQuotes.obligationId,
|
|
7808
|
+
ask: obligationsWithQuotes.ask,
|
|
7809
|
+
bid: obligationsWithQuotes.bid,
|
|
7810
|
+
maturity: obligationsWithQuotes.maturity
|
|
7811
|
+
};
|
|
7812
|
+
const rows = await db.select({
|
|
7813
|
+
obligationId: obligationsWithQuotes.obligationId,
|
|
7814
|
+
chainId: obligationsWithQuotes.chainId,
|
|
7815
|
+
loanToken: obligationsWithQuotes.loanToken,
|
|
7816
|
+
collaterals: obligationsWithQuotes.collaterals,
|
|
7817
|
+
maturity: obligationsWithQuotes.maturity,
|
|
7818
|
+
askTick: obligationsWithQuotes.askTick,
|
|
7819
|
+
bidTick: obligationsWithQuotes.bidTick,
|
|
7820
|
+
ask: obligationsWithQuotes.ask,
|
|
7821
|
+
bid: obligationsWithQuotes.bid
|
|
7822
|
+
}).from(obligationsWithQuotes).where(buildCursorFilter(sortColumns, sort, cursorValues)).orderBy(...buildOrderBy(sortColumns, sort)).limit(limit + 1);
|
|
7823
|
+
const hasMore = rows.length > limit;
|
|
7824
|
+
const listedRows = (hasMore ? rows.slice(0, limit) : rows).map((row) => {
|
|
7825
|
+
return {
|
|
7826
|
+
obligation: from$15({
|
|
7827
|
+
chainId: row.chainId,
|
|
7828
|
+
loanToken: row.loanToken,
|
|
7829
|
+
collaterals: row.collaterals.sort((left, right) => left.asset.localeCompare(right.asset)).map((collateral) => from$17({
|
|
7830
|
+
asset: collateral.asset,
|
|
7831
|
+
oracle: collateral.oracle,
|
|
7832
|
+
lltv: from$18(BigInt(collateral.lltv))
|
|
7833
|
+
})),
|
|
7834
|
+
maturity: row.maturity
|
|
7835
|
+
}),
|
|
7836
|
+
quote: from$11({
|
|
7837
|
+
obligationId: row.obligationId,
|
|
7838
|
+
ask: { tick: row.askTick },
|
|
7839
|
+
bid: { tick: row.bidTick }
|
|
7840
|
+
}),
|
|
7841
|
+
cursorValues: {
|
|
7842
|
+
id: row.obligationId,
|
|
7843
|
+
ask: toBigInt(row.ask),
|
|
7844
|
+
bid: toBigInt(row.bid),
|
|
7845
|
+
maturity: row.maturity
|
|
7846
|
+
}
|
|
7847
|
+
};
|
|
7848
|
+
});
|
|
7849
|
+
const nextCursor = hasMore && listedRows.length > 0 ? encodeCursorPayload({
|
|
7850
|
+
sort: sortToTokens(sort),
|
|
7851
|
+
id: listedRows[listedRows.length - 1].cursorValues.id,
|
|
7852
|
+
ask: listedRows[listedRows.length - 1].cursorValues.ask.toString(),
|
|
7853
|
+
bid: listedRows[listedRows.length - 1].cursorValues.bid.toString(),
|
|
7854
|
+
maturity: listedRows[listedRows.length - 1].cursorValues.maturity
|
|
7855
|
+
}) : null;
|
|
7856
|
+
return {
|
|
7857
|
+
obligations: listedRows.map((row) => ({
|
|
7858
|
+
obligation: row.obligation,
|
|
7859
|
+
quote: row.quote
|
|
7860
|
+
})),
|
|
7861
|
+
nextCursor
|
|
7862
|
+
};
|
|
7863
|
+
} };
|
|
7864
|
+
}
|
|
7865
|
+
function isSortField(value) {
|
|
7866
|
+
return SORT_FIELDS.includes(value);
|
|
7867
|
+
}
|
|
7868
|
+
function parseSortToken(token) {
|
|
7869
|
+
const direction = token.startsWith("-") ? "desc" : "asc";
|
|
7870
|
+
const rawField = token.startsWith("-") ? token.slice(1) : token;
|
|
7871
|
+
if (!isSortField(rawField)) throw new BadRequestError(`Invalid sort field: ${rawField}`);
|
|
7872
|
+
return {
|
|
7873
|
+
field: rawField,
|
|
7874
|
+
direction
|
|
7875
|
+
};
|
|
7876
|
+
}
|
|
7877
|
+
function normalizeSort(sortTokens) {
|
|
7878
|
+
const parsed = sortTokens?.length ? sortTokens.map(parseSortToken) : [{
|
|
7879
|
+
field: "id",
|
|
7880
|
+
direction: "asc"
|
|
7881
|
+
}];
|
|
7882
|
+
return parsed.some((entry) => entry.field === "id") ? parsed : [...parsed, {
|
|
7883
|
+
field: "id",
|
|
7884
|
+
direction: "asc"
|
|
7885
|
+
}];
|
|
7886
|
+
}
|
|
7887
|
+
function sortToTokens(sortEntries) {
|
|
7888
|
+
return sortEntries.map((entry) => entry.direction === "desc" ? `-${entry.field}` : entry.field);
|
|
7889
|
+
}
|
|
7890
|
+
function hasSameSort(left, right) {
|
|
7891
|
+
if (left.length !== right.length) return false;
|
|
7892
|
+
return left.every((sortEntry, index) => sortEntry.field === right[index]?.field && sortEntry.direction === right[index]?.direction);
|
|
7893
|
+
}
|
|
7894
|
+
function decodeCursorPayload(cursor) {
|
|
7895
|
+
let decoded;
|
|
7896
|
+
try {
|
|
7897
|
+
decoded = JSON.parse(Buffer.from(cursor, "base64url").toString("utf8"));
|
|
7898
|
+
} catch {
|
|
7899
|
+
throw new BadRequestError("Invalid cursor format");
|
|
7900
|
+
}
|
|
7901
|
+
if (decoded === null || typeof decoded !== "object") throw new BadRequestError("Invalid cursor payload");
|
|
7902
|
+
const payload = decoded;
|
|
7903
|
+
const sortTokens = parseCursorSortTokens(payload.sort);
|
|
7904
|
+
if (typeof payload.id !== "string" || !CURSOR_ID_REGEX.test(payload.id)) throw new BadRequestError("Invalid cursor obligation id");
|
|
7905
|
+
const ask = parseCursorNonNegativeInt32(payload.ask, "ask");
|
|
7906
|
+
const bid = parseCursorNonNegativeInt32(payload.bid, "bid");
|
|
7907
|
+
if (!isInt32(payload.maturity)) throw new BadRequestError("Invalid cursor maturity value");
|
|
7908
|
+
return {
|
|
7909
|
+
sort: sortTokens,
|
|
7910
|
+
id: payload.id,
|
|
7911
|
+
ask,
|
|
7912
|
+
bid,
|
|
7913
|
+
maturity: payload.maturity
|
|
7914
|
+
};
|
|
7915
|
+
}
|
|
7916
|
+
function parseCursorSortTokens(value) {
|
|
7917
|
+
if (!Array.isArray(value) || value.length === 0 || value.length > MAX_CURSOR_SORT_FIELDS) throw new BadRequestError("Invalid cursor sort");
|
|
7918
|
+
const sortEntries = value.map((token) => {
|
|
7919
|
+
if (typeof token !== "string") throw new BadRequestError("Invalid cursor sort");
|
|
7920
|
+
try {
|
|
7921
|
+
return parseSortToken(token);
|
|
7922
|
+
} catch {
|
|
7923
|
+
throw new BadRequestError("Invalid cursor sort");
|
|
7924
|
+
}
|
|
7925
|
+
});
|
|
7926
|
+
if (new Set(sortEntries.map((entry) => entry.field)).size !== sortEntries.length) throw new BadRequestError("Invalid cursor sort");
|
|
7927
|
+
return sortToTokens(sortEntries);
|
|
7928
|
+
}
|
|
7929
|
+
function parseCursorNonNegativeInt32(value, field) {
|
|
7930
|
+
if (typeof value !== "string" || !/^\d+$/.test(value)) throw new BadRequestError(`Invalid cursor ${field} value`);
|
|
7931
|
+
if (BigInt(value) > INT32_MAX_BIGINT) throw new BadRequestError(`Invalid cursor ${field} value`);
|
|
7932
|
+
return value;
|
|
7933
|
+
}
|
|
7934
|
+
function isInt32(value) {
|
|
7935
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= INT32_MIN && value <= INT32_MAX;
|
|
7936
|
+
}
|
|
7937
|
+
function encodeCursorPayload(payload) {
|
|
7938
|
+
return Buffer.from(JSON.stringify(payload), "utf8").toString("base64url");
|
|
7939
|
+
}
|
|
7940
|
+
function cursorValuesFromPayload(payload) {
|
|
7941
|
+
return {
|
|
7942
|
+
id: payload.id,
|
|
7943
|
+
ask: BigInt(payload.ask),
|
|
7944
|
+
bid: BigInt(payload.bid),
|
|
7945
|
+
maturity: payload.maturity
|
|
7946
|
+
};
|
|
7947
|
+
}
|
|
7948
|
+
function cursorComparisonValue(cursorValues, field) {
|
|
7949
|
+
switch (field) {
|
|
7950
|
+
case "id": return cursorValues.id;
|
|
7951
|
+
case "maturity": return cursorValues.maturity;
|
|
7952
|
+
case "ask": return cursorValues.ask.toString();
|
|
7953
|
+
case "bid": return cursorValues.bid.toString();
|
|
7954
|
+
}
|
|
7955
|
+
}
|
|
7956
|
+
function buildCursorFilter(columns, sortEntries, cursorValues) {
|
|
7957
|
+
if (cursorValues === void 0) return void 0;
|
|
7958
|
+
const comparisons = sortEntries.map((sortEntry, index) => {
|
|
7959
|
+
const equals = sortEntries.slice(0, index).map((previous) => {
|
|
7960
|
+
return drizzle_orm.sql`${columns[previous.field]} = ${cursorComparisonValue(cursorValues, previous.field)}`;
|
|
7961
|
+
});
|
|
7962
|
+
const comparison = sortEntry.direction === "asc" ? drizzle_orm.sql`${columns[sortEntry.field]} > ${cursorComparisonValue(cursorValues, sortEntry.field)}` : drizzle_orm.sql`${columns[sortEntry.field]} < ${cursorComparisonValue(cursorValues, sortEntry.field)}`;
|
|
7963
|
+
return equals.length > 0 ? drizzle_orm.sql`(${drizzle_orm.sql.join([...equals, comparison], drizzle_orm.sql` AND `)})` : drizzle_orm.sql`(${comparison})`;
|
|
7964
|
+
});
|
|
7965
|
+
return comparisons.length > 0 ? drizzle_orm.sql`(${drizzle_orm.sql.join(comparisons, drizzle_orm.sql` OR `)})` : void 0;
|
|
7966
|
+
}
|
|
7967
|
+
function buildOrderBy(columns, sortEntries) {
|
|
7968
|
+
return sortEntries.map((sortEntry) => sortEntry.direction === "asc" ? (0, drizzle_orm.asc)(columns[sortEntry.field]) : (0, drizzle_orm.desc)(columns[sortEntry.field]));
|
|
7969
|
+
}
|
|
7970
|
+
function toBigInt(value) {
|
|
7971
|
+
if (typeof value === "bigint") return value;
|
|
7972
|
+
if (typeof value === "number") return BigInt(value);
|
|
7973
|
+
return BigInt(value.split(".")[0] ?? "0");
|
|
7974
|
+
}
|
|
7975
|
+
|
|
7654
7976
|
//#endregion
|
|
7655
7977
|
//#region src/api/Controllers/getObligation.ts
|
|
7978
|
+
function toPayloadError$1(err) {
|
|
7979
|
+
if (err instanceof BadRequestError) return new BadRequestError$1(err.message);
|
|
7980
|
+
return err;
|
|
7981
|
+
}
|
|
7656
7982
|
async function getObligation(params, db) {
|
|
7657
7983
|
const logger = getLogger();
|
|
7658
7984
|
const result = safeParse("get_obligation", params, (issue) => issue.message);
|
|
7659
7985
|
if (!result.success) return failure(result.error);
|
|
7660
7986
|
const query = result.data;
|
|
7661
7987
|
try {
|
|
7662
|
-
const
|
|
7663
|
-
|
|
7664
|
-
|
|
7665
|
-
|
|
7988
|
+
const listing = await db.readers.obligations.list({
|
|
7989
|
+
ids: [query.obligation_id],
|
|
7990
|
+
limit: 1
|
|
7991
|
+
});
|
|
7992
|
+
if (listing.obligations.length === 0) return failure(new NotFoundError("Obligation not found"));
|
|
7993
|
+
const obligation = listing.obligations[0];
|
|
7666
7994
|
return success({
|
|
7667
|
-
data: from$4(obligation, quote
|
|
7668
|
-
obligationId: id(obligation),
|
|
7669
|
-
ask: { price: 0n },
|
|
7670
|
-
bid: { price: 0n }
|
|
7671
|
-
}),
|
|
7995
|
+
data: from$4(obligation.obligation, obligation.quote),
|
|
7672
7996
|
cursor: null
|
|
7673
7997
|
});
|
|
7674
7998
|
} catch (err) {
|
|
7999
|
+
const payloadError = toPayloadError$1(err);
|
|
7675
8000
|
logger.error({
|
|
7676
|
-
err,
|
|
8001
|
+
err: payloadError,
|
|
7677
8002
|
msg: "Error get obligation",
|
|
7678
|
-
errorMessage:
|
|
7679
|
-
errorStack:
|
|
8003
|
+
errorMessage: payloadError instanceof Error ? payloadError.message : String(payloadError),
|
|
8004
|
+
errorStack: payloadError instanceof Error ? payloadError.stack : void 0
|
|
7680
8005
|
});
|
|
7681
|
-
return failure(
|
|
8006
|
+
return failure(payloadError);
|
|
7682
8007
|
}
|
|
7683
8008
|
}
|
|
7684
8009
|
|
|
7685
8010
|
//#endregion
|
|
7686
8011
|
//#region src/api/Controllers/getObligations.ts
|
|
8012
|
+
function toPayloadError(err) {
|
|
8013
|
+
if (err instanceof BadRequestError) return new BadRequestError$1(err.message);
|
|
8014
|
+
return err;
|
|
8015
|
+
}
|
|
7687
8016
|
async function getObligations$1(queryParameters, db) {
|
|
7688
8017
|
const logger = getLogger();
|
|
7689
8018
|
const result = safeParse("get_obligations", queryParameters, (issue) => issue.message);
|
|
@@ -7694,31 +8023,28 @@ async function getObligations$1(queryParameters, db) {
|
|
|
7694
8023
|
const loanTokens = query.loan_tokens?.length ? query.loan_tokens : void 0;
|
|
7695
8024
|
const collateralTokens = query.collateral_tokens?.length ? query.collateral_tokens : void 0;
|
|
7696
8025
|
const maturities = query.maturities?.length ? query.maturities : void 0;
|
|
7697
|
-
const
|
|
7698
|
-
cursor: query.cursor,
|
|
7699
|
-
limit: query.limit,
|
|
8026
|
+
const listing = await db.readers.obligations.list({
|
|
7700
8027
|
chainId: chainIds,
|
|
7701
8028
|
loanToken: loanTokens,
|
|
7702
8029
|
collateralToken: collateralTokens,
|
|
7703
|
-
maturity: maturities
|
|
8030
|
+
maturity: maturities,
|
|
8031
|
+
sort: query.sort,
|
|
8032
|
+
cursor: query.cursor,
|
|
8033
|
+
limit: query.limit
|
|
7704
8034
|
});
|
|
7705
|
-
const quotes = await db.offers.getQuotes({ obligationIds: obligations.map((o) => id(o)) });
|
|
7706
8035
|
return success({
|
|
7707
|
-
data: obligations.map((
|
|
7708
|
-
|
|
7709
|
-
ask: { price: 0n },
|
|
7710
|
-
bid: { price: 0n }
|
|
7711
|
-
})),
|
|
7712
|
-
cursor: nextCursor ?? null
|
|
8036
|
+
data: listing.obligations.map((item) => from$4(item.obligation, item.quote)),
|
|
8037
|
+
cursor: listing.nextCursor
|
|
7713
8038
|
});
|
|
7714
8039
|
} catch (err) {
|
|
8040
|
+
const payloadError = toPayloadError(err);
|
|
7715
8041
|
logger.error({
|
|
7716
|
-
err,
|
|
8042
|
+
err: payloadError,
|
|
7717
8043
|
msg: "Error get obligations",
|
|
7718
|
-
errorMessage:
|
|
7719
|
-
errorStack:
|
|
8044
|
+
errorMessage: payloadError instanceof Error ? payloadError.message : String(payloadError),
|
|
8045
|
+
errorStack: payloadError instanceof Error ? payloadError.stack : void 0
|
|
7720
8046
|
});
|
|
7721
|
-
return failure(
|
|
8047
|
+
return failure(payloadError);
|
|
7722
8048
|
}
|
|
7723
8049
|
}
|
|
7724
8050
|
|
|
@@ -7752,6 +8078,7 @@ function create$15(config) {
|
|
|
7752
8078
|
groupMaker: offer.maker.toLowerCase(),
|
|
7753
8079
|
callbackAddress: offer.callback.address.toLowerCase(),
|
|
7754
8080
|
callbackData: offer.callback.data,
|
|
8081
|
+
receiverIfMakerIsSeller: offer.receiverIfMakerIsSeller.toLowerCase(),
|
|
7755
8082
|
blockNumber
|
|
7756
8083
|
})));
|
|
7757
8084
|
if (offersRows.length === 0) return [];
|
|
@@ -7814,9 +8141,11 @@ function create$15(config) {
|
|
|
7814
8141
|
loanToken: obligations.loanToken,
|
|
7815
8142
|
callbackAddress: offers.callbackAddress,
|
|
7816
8143
|
callbackData: offers.callbackData,
|
|
8144
|
+
receiverIfMakerIsSeller: offers.receiverIfMakerIsSeller,
|
|
7817
8145
|
collaterals: collateralsLateral.collaterals,
|
|
7818
8146
|
blockNumber: offers.blockNumber
|
|
7819
8147
|
}).from(offers).innerJoin(obligations, (0, drizzle_orm.eq)(offers.obligationId, obligations.obligationId)).innerJoinLateral(collateralsLateral, drizzle_orm.sql`true`).where((0, drizzle_orm.and)(cursor !== null && cursor !== void 0 ? (0, drizzle_orm.gt)(offers.hash, cursor) : void 0, maker !== void 0 ? (0, drizzle_orm.eq)(offers.groupMaker, maker.toLowerCase()) : void 0)).orderBy((0, drizzle_orm.asc)(offers.hash)).limit(limit)).map((row) => {
|
|
8148
|
+
const receiverIfMakerIsSeller = (row.receiverIfMakerIsSeller ?? row.maker).toLowerCase();
|
|
7820
8149
|
return {
|
|
7821
8150
|
hash: row.hash,
|
|
7822
8151
|
maker: row.maker,
|
|
@@ -7841,6 +8170,7 @@ function create$15(config) {
|
|
|
7841
8170
|
address: row.callbackAddress,
|
|
7842
8171
|
data: row.callbackData
|
|
7843
8172
|
},
|
|
8173
|
+
receiverIfMakerIsSeller,
|
|
7844
8174
|
consumed: 0n,
|
|
7845
8175
|
available: 0n,
|
|
7846
8176
|
takeable: 0n,
|
|
@@ -7865,64 +8195,30 @@ function create$15(config) {
|
|
|
7865
8195
|
}
|
|
7866
8196
|
throw new Error("Invalid parameters");
|
|
7867
8197
|
},
|
|
7868
|
-
getObligations: async (parameters) => {
|
|
7869
|
-
const { ids, chainId: chainIds, loanToken: loanTokens, collateralToken: collateralTokens, maturity: maturities, cursor, limit = DEFAULT_LIMIT$3 } = parameters ?? {};
|
|
7870
|
-
const now$1 = now();
|
|
7871
|
-
const loanTokenFilter = loanTokens !== void 0 && loanTokens.length > 0 ? drizzle_orm.sql`(${drizzle_orm.sql.join(loanTokens.map((token) => drizzle_orm.sql`LOWER(${obligations.loanToken}) = ${token.toLowerCase()}`), drizzle_orm.sql` OR `)})` : void 0;
|
|
7872
|
-
const collateralFilter = collateralTokens !== void 0 && collateralTokens.length > 0 ? drizzle_orm.sql`EXISTS (
|
|
7873
|
-
SELECT 1 FROM ${obligationCollateralsV2} oc
|
|
7874
|
-
WHERE oc.obligation_id = ${obligations.obligationId}
|
|
7875
|
-
AND (${drizzle_orm.sql.join(collateralTokens.map((token) => drizzle_orm.sql`LOWER(oc.asset) = ${token.toLowerCase()}`), drizzle_orm.sql` OR `)})
|
|
7876
|
-
)` : void 0;
|
|
7877
|
-
const result = await db.select({
|
|
7878
|
-
obligationId: obligations.obligationId,
|
|
7879
|
-
chainId: obligations.chainId,
|
|
7880
|
-
loanToken: obligations.loanToken,
|
|
7881
|
-
collaterals: drizzle_orm.sql`ARRAY_AGG(jsonb_build_object('asset', ${obligationCollateralsV2.asset}, 'oracle', ${oracles$1.address}, 'lltv', ${obligationCollateralsV2.lltv}))`.as("collaterals"),
|
|
7882
|
-
maturity: obligations.maturity
|
|
7883
|
-
}).from(obligations).innerJoin(obligationCollateralsV2, (0, drizzle_orm.eq)(obligations.obligationId, obligationCollateralsV2.obligationId)).innerJoin(oracles$1, drizzle_orm.sql`${obligationCollateralsV2.oracleChainId} = ${oracles$1.chainId}
|
|
7884
|
-
AND ${obligationCollateralsV2.oracleAddress} = ${oracles$1.address}`).groupBy(obligations.obligationId).where((0, drizzle_orm.and)(cursor !== null && cursor !== void 0 ? (0, drizzle_orm.gt)(obligations.obligationId, cursor) : drizzle_orm.sql`true`, ids !== void 0 && ids.length > 0 ? (0, drizzle_orm.inArray)(obligations.obligationId, ids) : void 0, chainIds !== void 0 && chainIds.length > 0 ? (0, drizzle_orm.inArray)(obligations.chainId, chainIds) : void 0, loanTokenFilter, maturities !== void 0 && maturities.length > 0 ? (0, drizzle_orm.inArray)(obligations.maturity, maturities) : (0, drizzle_orm.gte)(obligations.maturity, now$1), collateralFilter)).orderBy((0, drizzle_orm.asc)(obligations.obligationId)).limit(limit);
|
|
7885
|
-
const items = [];
|
|
7886
|
-
for (const row of result) items.push(from$15({
|
|
7887
|
-
chainId: row.chainId,
|
|
7888
|
-
loanToken: row.loanToken,
|
|
7889
|
-
collaterals: row.collaterals.sort((a, b) => a.asset.localeCompare(b.asset)).map((c) => from$17({
|
|
7890
|
-
asset: c.asset,
|
|
7891
|
-
oracle: c.oracle,
|
|
7892
|
-
lltv: from$18(BigInt(c.lltv))
|
|
7893
|
-
})),
|
|
7894
|
-
maturity: row.maturity
|
|
7895
|
-
}));
|
|
7896
|
-
const returnedItems = Array.from(items.values());
|
|
7897
|
-
return {
|
|
7898
|
-
obligations: returnedItems,
|
|
7899
|
-
nextCursor: returnedItems.length === limit && returnedItems.length > 0 ? result[result.length - 1].obligationId : null
|
|
7900
|
-
};
|
|
7901
|
-
},
|
|
7902
8198
|
getQuotes: async (parameters) => {
|
|
7903
8199
|
const { obligationIds } = parameters;
|
|
7904
8200
|
if (obligationIds.length === 0) return [];
|
|
7905
8201
|
const now$2 = now();
|
|
7906
8202
|
const query = ({ side }) => db.selectDistinctOn([offers.obligationId], {
|
|
7907
8203
|
obligationId: offers.obligationId,
|
|
7908
|
-
|
|
8204
|
+
tick: offers.tick
|
|
7909
8205
|
}).from(offers).innerJoin(groups, (0, drizzle_orm.and)((0, drizzle_orm.eq)(offers.groupChainId, groups.chainId), (0, drizzle_orm.eq)(offers.groupMaker, groups.maker), (0, drizzle_orm.eq)(offers.group, groups.group))).leftJoin(validations, (0, drizzle_orm.eq)(offers.hash, validations.offerHash)).leftJoin(status, (0, drizzle_orm.eq)(validations.statusId, status.id)).where((0, drizzle_orm.and)((0, drizzle_orm.inArray)(offers.obligationId, obligationIds), (0, drizzle_orm.eq)(offers.buy, side === "buy"), (0, drizzle_orm.gte)(offers.expiry, now$2), (0, drizzle_orm.gte)(offers.maturity, now$2), (0, drizzle_orm.lte)(offers.start, now$2), drizzle_orm.sql`(${status.code} IS NULL OR ${status.code} = ${Status.VALID})`)).orderBy(offers.obligationId, side === "buy" ? drizzle_orm.sql`${offers.tick} ASC` : drizzle_orm.sql`${offers.tick} DESC`);
|
|
7910
8206
|
const [bestBuys, bestSells] = await Promise.all([query({ side: "buy" }), query({ side: "sell" })]);
|
|
7911
8207
|
const quotes = /* @__PURE__ */ new Map();
|
|
7912
8208
|
for (const row of bestSells) quotes.set(row.obligationId, {
|
|
7913
|
-
ask: {
|
|
7914
|
-
bid: {
|
|
8209
|
+
ask: { tick: row.tick },
|
|
8210
|
+
bid: { tick: null }
|
|
7915
8211
|
});
|
|
7916
8212
|
for (const row of bestBuys) {
|
|
7917
8213
|
const quote = quotes.get(row.obligationId);
|
|
7918
8214
|
if (!quote) {
|
|
7919
8215
|
quotes.set(row.obligationId, {
|
|
7920
|
-
ask: {
|
|
7921
|
-
bid: {
|
|
8216
|
+
ask: { tick: null },
|
|
8217
|
+
bid: { tick: row.tick }
|
|
7922
8218
|
});
|
|
7923
8219
|
continue;
|
|
7924
8220
|
}
|
|
7925
|
-
quote.bid = {
|
|
8221
|
+
quote.bid = { tick: row.tick };
|
|
7926
8222
|
}
|
|
7927
8223
|
return Array.from(quotes.entries()).map(([id, quote]) => {
|
|
7928
8224
|
return from$11({
|
|
@@ -8033,6 +8329,7 @@ async function getOffersQuery(db, parameters) {
|
|
|
8033
8329
|
loanToken: obligations.loanToken,
|
|
8034
8330
|
callbackAddress: offers.callbackAddress,
|
|
8035
8331
|
callbackData: offers.callbackData,
|
|
8332
|
+
receiverIfMakerIsSeller: offers.receiverIfMakerIsSeller,
|
|
8036
8333
|
collaterals: collateralsLateral.collaterals,
|
|
8037
8334
|
blockNumber: offers.blockNumber,
|
|
8038
8335
|
available: drizzle_orm.sql`${availableExpr}::numeric`.as("available"),
|
|
@@ -8054,6 +8351,7 @@ async function getOffersQuery(db, parameters) {
|
|
|
8054
8351
|
)
|
|
8055
8352
|
END
|
|
8056
8353
|
) > 0` : void 0)).orderBy((0, drizzle_orm.asc)(offers.hash)).limit(limit)).map((row) => {
|
|
8354
|
+
const receiverIfMakerIsSeller = (row.receiverIfMakerIsSeller ?? row.maker).toLowerCase();
|
|
8057
8355
|
return {
|
|
8058
8356
|
hash: row.hash,
|
|
8059
8357
|
maker: row.maker,
|
|
@@ -8078,6 +8376,7 @@ async function getOffersQuery(db, parameters) {
|
|
|
8078
8376
|
address: row.callbackAddress,
|
|
8079
8377
|
data: row.callbackData
|
|
8080
8378
|
},
|
|
8379
|
+
receiverIfMakerIsSeller,
|
|
8081
8380
|
consumed: BigInt(row.consumed),
|
|
8082
8381
|
available: BigInt(String(row.available ?? "0").split(".")[0] ?? "0"),
|
|
8083
8382
|
takeable: BigInt(String(row.takeable ?? "0").split(".")[0] ?? "0"),
|
|
@@ -8168,7 +8467,7 @@ async function getUserPositions(queryParameters, db) {
|
|
|
8168
8467
|
async function validateOffers(body, gatekeeper) {
|
|
8169
8468
|
const logger = getLogger();
|
|
8170
8469
|
const result = safeParse("validate_offers", body, (issue) => issue.message);
|
|
8171
|
-
if (!result.success) return failure(new BadRequestError(result.error.issues[0]?.message ?? "Invalid request body"));
|
|
8470
|
+
if (!result.success) return failure(new BadRequestError$1(result.error.issues[0]?.message ?? "Invalid request body"));
|
|
8172
8471
|
const { offers: rawOffers } = result.data;
|
|
8173
8472
|
const parsedOffers = [];
|
|
8174
8473
|
const offerIndexByHash = /* @__PURE__ */ new Map();
|
|
@@ -8184,7 +8483,7 @@ async function validateOffers(body, gatekeeper) {
|
|
|
8184
8483
|
} catch (err) {
|
|
8185
8484
|
let message = err instanceof Error ? err.message : String(err);
|
|
8186
8485
|
if (err instanceof InvalidOfferError) message = err.formattedMessage;
|
|
8187
|
-
return failure(new BadRequestError(`Offer at index ${i} failed to parse: ${message}`));
|
|
8486
|
+
return failure(new BadRequestError$1(`Offer at index ${i} failed to parse: ${message}`));
|
|
8188
8487
|
}
|
|
8189
8488
|
}
|
|
8190
8489
|
try {
|
|
@@ -8476,7 +8775,8 @@ async function getOffers(apiClient, parameters) {
|
|
|
8476
8775
|
callback: {
|
|
8477
8776
|
address: offerData.callback,
|
|
8478
8777
|
data: offerData.callback_data
|
|
8479
|
-
}
|
|
8778
|
+
},
|
|
8779
|
+
receiver_if_maker_is_seller: offerData.receiver_if_maker_is_seller
|
|
8480
8780
|
}),
|
|
8481
8781
|
hash: item.offer_hash,
|
|
8482
8782
|
consumed: BigInt(item.consumed),
|
|
@@ -8493,13 +8793,15 @@ async function getOffers(apiClient, parameters) {
|
|
|
8493
8793
|
};
|
|
8494
8794
|
}
|
|
8495
8795
|
async function getObligations(apiClient, parameters) {
|
|
8796
|
+
const sort = parameters?.sort?.length ? parameters.sort.join(",") : void 0;
|
|
8496
8797
|
const { data, error, response } = await apiClient.GET("/v1/obligations", { params: { query: {
|
|
8497
8798
|
cursor: parameters?.cursor,
|
|
8498
8799
|
limit: parameters?.limit,
|
|
8499
8800
|
chains: parameters?.chainIds,
|
|
8500
8801
|
loan_tokens: parameters?.loanTokens,
|
|
8501
8802
|
collateral_tokens: parameters?.collateralTokens,
|
|
8502
|
-
maturities: parameters?.maturities
|
|
8803
|
+
maturities: parameters?.maturities,
|
|
8804
|
+
sort
|
|
8503
8805
|
} } });
|
|
8504
8806
|
if (error !== void 0) {
|
|
8505
8807
|
switch (response.status) {
|
|
@@ -8523,10 +8825,10 @@ async function getObligations(apiClient, parameters) {
|
|
|
8523
8825
|
const { obligationId: _, ...returned } = {
|
|
8524
8826
|
id: () => id(obligation),
|
|
8525
8827
|
...obligation,
|
|
8526
|
-
...
|
|
8527
|
-
|
|
8528
|
-
ask: item.ask,
|
|
8529
|
-
bid: item.bid
|
|
8828
|
+
...from$11({
|
|
8829
|
+
obligationId: item.id,
|
|
8830
|
+
ask: { tick: item.ask.tick },
|
|
8831
|
+
bid: { tick: item.bid.tick }
|
|
8530
8832
|
})
|
|
8531
8833
|
};
|
|
8532
8834
|
return returned;
|
|
@@ -8982,6 +9284,7 @@ async function _getOffers(db, params) {
|
|
|
8982
9284
|
p.buy,
|
|
8983
9285
|
p.callback_address,
|
|
8984
9286
|
p.callback_data,
|
|
9287
|
+
p.receiver_if_maker_is_seller,
|
|
8985
9288
|
p.block_number,
|
|
8986
9289
|
p.group_chain_id,
|
|
8987
9290
|
p.group_maker,
|
|
@@ -9059,6 +9362,7 @@ async function _getOffers(db, params) {
|
|
|
9059
9362
|
buy,
|
|
9060
9363
|
callback_address,
|
|
9061
9364
|
callback_data,
|
|
9365
|
+
receiver_if_maker_is_seller,
|
|
9062
9366
|
block_number,
|
|
9063
9367
|
group_chain_id,
|
|
9064
9368
|
group_maker,
|
|
@@ -9076,8 +9380,8 @@ async function _getOffers(db, params) {
|
|
|
9076
9380
|
ORDER BY clc.hash, clc.position_chain_id, clc.position_contract, clc.position_user, clc.contribution_in_loan DESC
|
|
9077
9381
|
) deduped
|
|
9078
9382
|
GROUP BY hash, obligation_id, assets, tick, obligation_units, obligation_shares, maturity, expiry, start, group_group, buy,
|
|
9079
|
-
|
|
9080
|
-
consumed, chain_id, loan_token, session
|
|
9383
|
+
callback_address, callback_data, block_number, group_chain_id, group_maker,
|
|
9384
|
+
consumed, chain_id, loan_token, session, receiver_if_maker_is_seller
|
|
9081
9385
|
UNION ALL
|
|
9082
9386
|
-- Sell offers without callbacks: collateral positions not indexed, takeable = assets - consumed
|
|
9083
9387
|
SELECT
|
|
@@ -9085,6 +9389,7 @@ async function _getOffers(db, params) {
|
|
|
9085
9389
|
p.obligation_units, p.obligation_shares,
|
|
9086
9390
|
p.maturity, p.expiry, p.start, p.group_group,
|
|
9087
9391
|
p.buy, p.callback_address, p.callback_data,
|
|
9392
|
+
p.receiver_if_maker_is_seller,
|
|
9088
9393
|
p.block_number, p.group_chain_id, p.group_maker,
|
|
9089
9394
|
p.consumed, p.chain_id, p.loan_token, p.session,
|
|
9090
9395
|
0 AS total_available
|
|
@@ -9113,6 +9418,7 @@ async function _getOffers(db, params) {
|
|
|
9113
9418
|
oc.loan_token,
|
|
9114
9419
|
oc.callback_address,
|
|
9115
9420
|
oc.callback_data,
|
|
9421
|
+
oc.receiver_if_maker_is_seller,
|
|
9116
9422
|
oc.block_number,
|
|
9117
9423
|
oc.session,
|
|
9118
9424
|
COALESCE(oc.total_available, 0) AS available,
|
|
@@ -9142,6 +9448,7 @@ async function _getOffers(db, params) {
|
|
|
9142
9448
|
`);
|
|
9143
9449
|
return {
|
|
9144
9450
|
rows: raw.rows.map((row) => {
|
|
9451
|
+
const receiverIfMakerIsSeller = (row.receiver_if_maker_is_seller ?? row.group_maker).toLowerCase();
|
|
9145
9452
|
return {
|
|
9146
9453
|
hash: row.hash,
|
|
9147
9454
|
maker: row.group_maker,
|
|
@@ -9166,6 +9473,7 @@ async function _getOffers(db, params) {
|
|
|
9166
9473
|
address: row.callback_address,
|
|
9167
9474
|
data: row.callback_data
|
|
9168
9475
|
},
|
|
9476
|
+
receiverIfMakerIsSeller,
|
|
9169
9477
|
blockNumber: row.block_number,
|
|
9170
9478
|
consumed: BigInt(row.consumed ?? 0),
|
|
9171
9479
|
available: BigInt(String(row.available ?? "0").split(".")[0] ?? "0"),
|
|
@@ -9415,38 +9723,60 @@ function create$8(db) {
|
|
|
9415
9723
|
* @returns Obligations domain. {@link ObligationsDomain}
|
|
9416
9724
|
*/
|
|
9417
9725
|
function create$7(db) {
|
|
9418
|
-
return {
|
|
9419
|
-
|
|
9420
|
-
|
|
9421
|
-
|
|
9422
|
-
|
|
9423
|
-
|
|
9424
|
-
|
|
9425
|
-
|
|
9426
|
-
|
|
9427
|
-
|
|
9428
|
-
|
|
9429
|
-
|
|
9430
|
-
|
|
9431
|
-
|
|
9432
|
-
|
|
9433
|
-
|
|
9434
|
-
|
|
9435
|
-
|
|
9726
|
+
return {
|
|
9727
|
+
get: async (parameters) => {
|
|
9728
|
+
const chainIds = parameters?.chainId;
|
|
9729
|
+
const now$1 = now();
|
|
9730
|
+
return (await db.select({
|
|
9731
|
+
chainId: obligations.chainId,
|
|
9732
|
+
loanToken: obligations.loanToken,
|
|
9733
|
+
collaterals: drizzle_orm.sql`ARRAY_AGG(jsonb_build_object('asset', ${obligationCollateralsV2.asset}, 'oracle', ${oracles$1.address}, 'lltv', ${obligationCollateralsV2.lltv}))`.as("collaterals"),
|
|
9734
|
+
maturity: obligations.maturity
|
|
9735
|
+
}).from(obligations).innerJoin(obligationCollateralsV2, (0, drizzle_orm.eq)(obligations.obligationId, obligationCollateralsV2.obligationId)).innerJoin(oracles$1, drizzle_orm.sql`${obligationCollateralsV2.oracleChainId} = ${oracles$1.chainId}
|
|
9736
|
+
AND ${obligationCollateralsV2.oracleAddress} = ${oracles$1.address}`).groupBy(obligations.obligationId).where((0, drizzle_orm.and)(chainIds !== void 0 && chainIds.length > 0 ? (0, drizzle_orm.inArray)(obligations.chainId, chainIds) : void 0, (0, drizzle_orm.gte)(obligations.maturity, now$1))).orderBy((0, drizzle_orm.asc)(obligations.obligationId))).map((row) => from$15({
|
|
9737
|
+
chainId: row.chainId,
|
|
9738
|
+
loanToken: row.loanToken,
|
|
9739
|
+
collaterals: row.collaterals.sort((left, right) => left.asset.localeCompare(right.asset)).map((collateral) => from$17({
|
|
9740
|
+
asset: collateral.asset,
|
|
9741
|
+
oracle: collateral.oracle,
|
|
9742
|
+
lltv: from$18(BigInt(collateral.lltv))
|
|
9743
|
+
})),
|
|
9744
|
+
maturity: row.maturity
|
|
9745
|
+
}));
|
|
9746
|
+
},
|
|
9747
|
+
create: async (obligations$1) => {
|
|
9748
|
+
if (obligations$1.length === 0) return;
|
|
9749
|
+
const obligationsById = /* @__PURE__ */ new Map();
|
|
9750
|
+
for (const obligation of obligations$1) {
|
|
9751
|
+
const id$1 = id(obligation).toLowerCase();
|
|
9752
|
+
if (!obligationsById.get(id$1)) obligationsById.set(id$1, obligation);
|
|
9753
|
+
}
|
|
9754
|
+
try {
|
|
9755
|
+
await db.transaction(async (dbTx) => {
|
|
9756
|
+
const obligationRows = obligations$1.map((obligation) => ({
|
|
9436
9757
|
obligationId: id(obligation),
|
|
9437
|
-
|
|
9438
|
-
|
|
9439
|
-
|
|
9440
|
-
lltv: collateral.lltv
|
|
9758
|
+
chainId: obligation.chainId,
|
|
9759
|
+
loanToken: obligation.loanToken.toLowerCase(),
|
|
9760
|
+
maturity: obligation.maturity
|
|
9441
9761
|
}));
|
|
9762
|
+
for (const batch of batch$1(obligationRows, DEFAULT_BATCH_SIZE$1)) await dbTx.insert(obligations).values(batch).onConflictDoNothing();
|
|
9763
|
+
const collateralRows = obligations$1.flatMap((obligation) => {
|
|
9764
|
+
return obligation.collaterals.map((collateral) => ({
|
|
9765
|
+
obligationId: id(obligation),
|
|
9766
|
+
asset: collateral.asset.toLowerCase(),
|
|
9767
|
+
oracleChainId: obligation.chainId,
|
|
9768
|
+
oracleAddress: collateral.oracle.toLowerCase(),
|
|
9769
|
+
lltv: collateral.lltv
|
|
9770
|
+
}));
|
|
9771
|
+
});
|
|
9772
|
+
for (const batch of batch$1(collateralRows, DEFAULT_BATCH_SIZE$1)) await dbTx.insert(obligationCollateralsV2).values(batch).onConflictDoNothing();
|
|
9442
9773
|
});
|
|
9443
|
-
|
|
9444
|
-
|
|
9445
|
-
|
|
9446
|
-
|
|
9447
|
-
throw new Error("Obligations.create failed. Ensure oracles exist before inserting obligations.", { cause: error });
|
|
9774
|
+
} catch (err) {
|
|
9775
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
9776
|
+
throw new Error("Obligations.create failed. Ensure oracles exist before inserting obligations.", { cause: error });
|
|
9777
|
+
}
|
|
9448
9778
|
}
|
|
9449
|
-
}
|
|
9779
|
+
};
|
|
9450
9780
|
}
|
|
9451
9781
|
|
|
9452
9782
|
//#endregion
|
|
@@ -10031,6 +10361,9 @@ function createDomains(core, chainRegistry) {
|
|
|
10031
10361
|
transfers: create$3(core)
|
|
10032
10362
|
};
|
|
10033
10363
|
}
|
|
10364
|
+
function createReaders(core) {
|
|
10365
|
+
return { obligations: create$16({ db: core }) };
|
|
10366
|
+
}
|
|
10034
10367
|
const AUGMENT_CACHE = /* @__PURE__ */ new WeakMap();
|
|
10035
10368
|
function augmentWithDomains(base, chainRegistry) {
|
|
10036
10369
|
const cached = AUGMENT_CACHE.get(base)?.get(chainRegistry);
|
|
@@ -10042,6 +10375,7 @@ function augmentWithDomains(base, chainRegistry) {
|
|
|
10042
10375
|
});
|
|
10043
10376
|
};
|
|
10044
10377
|
const dms = createDomains(wrapped, chainRegistry);
|
|
10378
|
+
const readers = createReaders(wrapped);
|
|
10045
10379
|
Object.defineProperties(wrapped, {
|
|
10046
10380
|
book: {
|
|
10047
10381
|
value: dms.book,
|
|
@@ -10098,6 +10432,10 @@ function augmentWithDomains(base, chainRegistry) {
|
|
|
10098
10432
|
transfers: {
|
|
10099
10433
|
value: dms.transfers,
|
|
10100
10434
|
enumerable: true
|
|
10435
|
+
},
|
|
10436
|
+
readers: {
|
|
10437
|
+
value: readers,
|
|
10438
|
+
enumerable: true
|
|
10101
10439
|
}
|
|
10102
10440
|
});
|
|
10103
10441
|
const chainRegistryMap = AUGMENT_CACHE.get(base);
|
|
@@ -10737,7 +11075,7 @@ const chains = ({ chains }) => single("chain_ids", `Validates that offer chain i
|
|
|
10737
11075
|
});
|
|
10738
11076
|
const maturity = ({ maturities }) => single("maturity", `Validates that offer maturity is one of: [${maturities.join(", ")}]`, (offer) => {
|
|
10739
11077
|
const allowedMaturities = maturities.map((m) => from$16(m));
|
|
10740
|
-
if (!allowedMaturities.includes(offer.maturity)) return { message: `Maturity must be
|
|
11078
|
+
if (!allowedMaturities.includes(offer.maturity)) return { message: `Maturity must be one of (${allowedMaturities.join(", ")}). Got: ${offer.maturity}` };
|
|
10741
11079
|
});
|
|
10742
11080
|
const callback = ({ callbacks }) => single("callback", `Validates callbacks: buy empty callback is ${callbacks.includes(Type$1.BuyWithEmptyCallback) ? "allowed" : "not allowed"}; sell empty callback is ${callbacks.includes(Type$1.SellWithEmptyCallback) ? "allowed" : "not allowed"}; non-empty callbacks are rejected`, (offer) => {
|
|
10743
11081
|
if (!isEmptyCallback(offer)) return { message: "Non-empty callbacks are not supported." };
|
|
@@ -10817,7 +11155,7 @@ const morphoRules = (chains$3) => {
|
|
|
10817
11155
|
sameMaker(),
|
|
10818
11156
|
amountMutualExclusivity(),
|
|
10819
11157
|
chains({ chains: chains$3 }),
|
|
10820
|
-
maturity({ maturities: [MaturityType.
|
|
11158
|
+
maturity({ maturities: [MaturityType.EndOfWeek, MaturityType.EndOfNextWeek] }),
|
|
10821
11159
|
callback({
|
|
10822
11160
|
callbacks: [Type$1.BuyWithEmptyCallback, Type$1.SellWithEmptyCallback],
|
|
10823
11161
|
allowedAddresses: []
|