@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.mjs
CHANGED
|
@@ -12,7 +12,7 @@ import "@opentelemetry/propagator-aws-xray";
|
|
|
12
12
|
import "@opentelemetry/resources";
|
|
13
13
|
import "@opentelemetry/sdk-trace-node";
|
|
14
14
|
import "@opentelemetry/semantic-conventions";
|
|
15
|
-
import { and, asc, eq, gt, gte, inArray, lte, ne, sql } from "drizzle-orm";
|
|
15
|
+
import { and, asc, desc, eq, gt, gte, inArray, lte, ne, sql } from "drizzle-orm";
|
|
16
16
|
import { anvil, base, mainnet } from "viem/chains";
|
|
17
17
|
import * as z$1 from "zod";
|
|
18
18
|
import { StandardMerkleTree } from "@openzeppelin/merkle-tree";
|
|
@@ -566,7 +566,7 @@ var utils_exports = /* @__PURE__ */ __exportAll({
|
|
|
566
566
|
|
|
567
567
|
//#endregion
|
|
568
568
|
//#region src/indexer/collectors/Admin.ts
|
|
569
|
-
function create$
|
|
569
|
+
function create$21(parameters) {
|
|
570
570
|
const collector = "admin";
|
|
571
571
|
const { client, db, options: { maxBatchSize = 25, maxBlockNumber } = {} } = parameters;
|
|
572
572
|
const maxBlockNumberBI = maxBlockNumber !== void 0 ? BigInt(maxBlockNumber) : void 0;
|
|
@@ -806,8 +806,8 @@ const names = [
|
|
|
806
806
|
"positions",
|
|
807
807
|
"prices"
|
|
808
808
|
];
|
|
809
|
-
function create$
|
|
810
|
-
const admin = create$
|
|
809
|
+
function create$20({ name, collect, client, db, options }) {
|
|
810
|
+
const admin = create$21({
|
|
811
811
|
client,
|
|
812
812
|
db,
|
|
813
813
|
options
|
|
@@ -973,18 +973,18 @@ const MorphoV2 = parseAbi([
|
|
|
973
973
|
"function setFeeSetter(address newFeeSetter)",
|
|
974
974
|
"function setObligationTradingFee(bytes32 id, uint256 index, uint256 newTradingFee)",
|
|
975
975
|
"function setOwner(address newOwner)",
|
|
976
|
-
"function setTradingFeeRecipient(address
|
|
976
|
+
"function setTradingFeeRecipient(address feeRecipient)",
|
|
977
977
|
"function sharesOf(bytes32 id, address user) view returns (uint256)",
|
|
978
978
|
"function shuffleSession()",
|
|
979
979
|
"function supplyCollateral((address loanToken, (address token, uint256 lltv, address oracle)[] collaterals, uint256 maturity) obligation, address collateral, uint256 assets, address onBehalf)",
|
|
980
|
-
"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
|
|
980
|
+
"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)",
|
|
981
981
|
"function totalShares(bytes32 id) view returns (uint256)",
|
|
982
982
|
"function totalUnits(bytes32 id) view returns (uint256)",
|
|
983
983
|
"function touchObligation((address loanToken, (address token, uint256 lltv, address oracle)[] collaterals, uint256 maturity) obligation) returns (bytes32)",
|
|
984
984
|
"function tradingFee(bytes32 id, uint256 timeToMaturity) view returns (uint256)",
|
|
985
985
|
"function tradingFeeRecipient() view returns (address)",
|
|
986
|
-
"function withdraw((address loanToken, (address token, uint256 lltv, address oracle)[] collaterals, uint256 maturity) obligation, uint256 obligationUnits, uint256 shares, address onBehalf) returns (uint256, uint256)",
|
|
987
|
-
"function withdrawCollateral((address loanToken, (address token, uint256 lltv, address oracle)[] collaterals, uint256 maturity) obligation, address collateral, uint256 assets, address onBehalf)",
|
|
986
|
+
"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)",
|
|
987
|
+
"function withdrawCollateral((address loanToken, (address token, uint256 lltv, address oracle)[] collaterals, uint256 maturity) obligation, address collateral, uint256 assets, address onBehalf, address receiver)",
|
|
988
988
|
"function withdrawable(bytes32 id) view returns (uint256)",
|
|
989
989
|
"event Constructor(address indexed owner)",
|
|
990
990
|
"event Consume(address indexed user, bytes32 indexed group, uint256 amount)",
|
|
@@ -996,12 +996,12 @@ const MorphoV2 = parseAbi([
|
|
|
996
996
|
"event SetFeeSetter(address indexed feeSetter)",
|
|
997
997
|
"event SetObligationTradingFee(bytes32 indexed id, uint256 indexed index, uint256 newTradingFee)",
|
|
998
998
|
"event SetOwner(address indexed owner)",
|
|
999
|
-
"event SetTradingFeeRecipient(address indexed
|
|
999
|
+
"event SetTradingFeeRecipient(address indexed feeRecipient)",
|
|
1000
1000
|
"event ShuffleSession(address indexed user, bytes32 session)",
|
|
1001
1001
|
"event SupplyCollateral(address caller, bytes32 indexed id, address indexed collateral, uint256 assets, address indexed onBehalf)",
|
|
1002
|
-
"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)",
|
|
1003
|
-
"event Withdraw(address
|
|
1004
|
-
"event WithdrawCollateral(address caller, bytes32 indexed id, address indexed collateral, uint256 assets, address indexed onBehalf)"
|
|
1002
|
+
"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)",
|
|
1003
|
+
"event Withdraw(address caller, bytes32 indexed id, uint256 obligationUnits, uint256 shares, address indexed onBehalf, address indexed receiver)",
|
|
1004
|
+
"event WithdrawCollateral(address caller, bytes32 indexed id, address indexed collateral, uint256 assets, address indexed onBehalf, address receiver)"
|
|
1005
1005
|
]);
|
|
1006
1006
|
|
|
1007
1007
|
//#endregion
|
|
@@ -1273,8 +1273,8 @@ const chains$2 = {
|
|
|
1273
1273
|
name: "ethereum-virtual-testnet",
|
|
1274
1274
|
custom: {
|
|
1275
1275
|
morpho: {
|
|
1276
|
-
address: "
|
|
1277
|
-
blockCreated:
|
|
1276
|
+
address: "0xc9f3c65996fc46b9500608b2c9a9152c01c540f7",
|
|
1277
|
+
blockCreated: 23226871
|
|
1278
1278
|
},
|
|
1279
1279
|
morphoBlue: {
|
|
1280
1280
|
address: "0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb",
|
|
@@ -1420,13 +1420,13 @@ var MissingBlockNumberError = class extends BaseError {
|
|
|
1420
1420
|
|
|
1421
1421
|
//#endregion
|
|
1422
1422
|
//#region src/core/ChainRegistry.ts
|
|
1423
|
-
var ChainRegistry_exports = /* @__PURE__ */ __exportAll({ create: () => create$
|
|
1423
|
+
var ChainRegistry_exports = /* @__PURE__ */ __exportAll({ create: () => create$19 });
|
|
1424
1424
|
/**
|
|
1425
1425
|
* Creates a chain registry from a list of chains.
|
|
1426
1426
|
* @param chains - Array of chain objects to register.
|
|
1427
1427
|
* @returns A registry for looking up chains by ID. {@link ChainRegistry}
|
|
1428
1428
|
*/
|
|
1429
|
-
function create$
|
|
1429
|
+
function create$19(chains) {
|
|
1430
1430
|
const byId = /* @__PURE__ */ new Map();
|
|
1431
1431
|
for (const chain of chains) byId.set(chain.id, chain);
|
|
1432
1432
|
return {
|
|
@@ -2101,7 +2101,8 @@ const OfferSchema = () => {
|
|
|
2101
2101
|
callback: z$1.object({
|
|
2102
2102
|
address: z$1.string().transform(transformAddress),
|
|
2103
2103
|
data: z$1.string().transform(transformHex)
|
|
2104
|
-
})
|
|
2104
|
+
}),
|
|
2105
|
+
receiverIfMakerIsSeller: z$1.string().transform(transformAddress)
|
|
2105
2106
|
}).refine((data) => data.start < data.expiry, {
|
|
2106
2107
|
message: "start must be before expiry",
|
|
2107
2108
|
path: ["start"]
|
|
@@ -2117,8 +2118,12 @@ const OfferSchema = () => {
|
|
|
2117
2118
|
* @returns The created offer.
|
|
2118
2119
|
*/
|
|
2119
2120
|
function from$14(input) {
|
|
2121
|
+
const normalizedInput = {
|
|
2122
|
+
...input,
|
|
2123
|
+
receiverIfMakerIsSeller: input.receiverIfMakerIsSeller ?? input.maker
|
|
2124
|
+
};
|
|
2120
2125
|
try {
|
|
2121
|
-
return OfferSchema().parse(
|
|
2126
|
+
return OfferSchema().parse(normalizedInput);
|
|
2122
2127
|
} catch (error) {
|
|
2123
2128
|
throw new InvalidOfferError(error);
|
|
2124
2129
|
}
|
|
@@ -2170,6 +2175,7 @@ const serialize = (offer) => ({
|
|
|
2170
2175
|
address: offer.callback.address,
|
|
2171
2176
|
data: offer.callback.data
|
|
2172
2177
|
},
|
|
2178
|
+
receiverIfMakerIsSeller: offer.receiverIfMakerIsSeller,
|
|
2173
2179
|
hash: hash(offer)
|
|
2174
2180
|
});
|
|
2175
2181
|
/**
|
|
@@ -2212,8 +2218,9 @@ function random$1(config) {
|
|
|
2212
2218
|
address: zeroAddress,
|
|
2213
2219
|
data: "0x"
|
|
2214
2220
|
};
|
|
2221
|
+
const maker = config?.maker ?? address();
|
|
2215
2222
|
return from$14({
|
|
2216
|
-
maker
|
|
2223
|
+
maker,
|
|
2217
2224
|
assets: assetsScaled,
|
|
2218
2225
|
obligationUnits: config?.obligationUnits ?? 0n,
|
|
2219
2226
|
obligationShares: config?.obligationShares ?? 0n,
|
|
@@ -2230,7 +2237,8 @@ function random$1(config) {
|
|
|
2230
2237
|
...random$3(),
|
|
2231
2238
|
lltv
|
|
2232
2239
|
})).sort((a, b) => a.asset.localeCompare(b.asset)),
|
|
2233
|
-
callback: config?.callback ?? emptyCallback
|
|
2240
|
+
callback: config?.callback ?? emptyCallback,
|
|
2241
|
+
receiverIfMakerIsSeller: config?.receiverIfMakerIsSeller ?? maker
|
|
2234
2242
|
});
|
|
2235
2243
|
}
|
|
2236
2244
|
const weightedChoice = (pairs) => {
|
|
@@ -2316,6 +2324,10 @@ const types = {
|
|
|
2316
2324
|
{
|
|
2317
2325
|
name: "callback",
|
|
2318
2326
|
type: "Callback"
|
|
2327
|
+
},
|
|
2328
|
+
{
|
|
2329
|
+
name: "receiverIfMakerIsSeller",
|
|
2330
|
+
type: "address"
|
|
2319
2331
|
}
|
|
2320
2332
|
],
|
|
2321
2333
|
Collateral: [
|
|
@@ -2361,7 +2373,8 @@ function hash(offer) {
|
|
|
2361
2373
|
callback: {
|
|
2362
2374
|
address: offer.callback.address.toLowerCase(),
|
|
2363
2375
|
data: offer.callback.data
|
|
2364
|
-
}
|
|
2376
|
+
},
|
|
2377
|
+
receiverIfMakerIsSeller: offer.receiverIfMakerIsSeller.toLowerCase()
|
|
2365
2378
|
},
|
|
2366
2379
|
primaryType: "Offer",
|
|
2367
2380
|
types
|
|
@@ -2464,6 +2477,10 @@ const OfferAbi = [
|
|
|
2464
2477
|
name: "data",
|
|
2465
2478
|
type: "bytes"
|
|
2466
2479
|
}]
|
|
2480
|
+
},
|
|
2481
|
+
{
|
|
2482
|
+
name: "receiverIfMakerIsSeller",
|
|
2483
|
+
type: "address"
|
|
2467
2484
|
}
|
|
2468
2485
|
];
|
|
2469
2486
|
function encode$1(offer) {
|
|
@@ -2482,7 +2499,8 @@ function encode$1(offer) {
|
|
|
2482
2499
|
offer.loanToken,
|
|
2483
2500
|
BigInt(offer.start),
|
|
2484
2501
|
offer.collaterals,
|
|
2485
|
-
offer.callback
|
|
2502
|
+
offer.callback,
|
|
2503
|
+
offer.receiverIfMakerIsSeller
|
|
2486
2504
|
]);
|
|
2487
2505
|
}
|
|
2488
2506
|
function decode$1(data) {
|
|
@@ -2516,7 +2534,8 @@ function decode$1(data) {
|
|
|
2516
2534
|
callback: {
|
|
2517
2535
|
address: decoded[14].address,
|
|
2518
2536
|
data: decoded[14].data
|
|
2519
|
-
}
|
|
2537
|
+
},
|
|
2538
|
+
receiverIfMakerIsSeller: decoded[15]
|
|
2520
2539
|
});
|
|
2521
2540
|
}
|
|
2522
2541
|
/**
|
|
@@ -2592,6 +2611,12 @@ const takeEvent = {
|
|
|
2592
2611
|
indexed: false,
|
|
2593
2612
|
internalType: "bool"
|
|
2594
2613
|
},
|
|
2614
|
+
{
|
|
2615
|
+
name: "sellerReceiver",
|
|
2616
|
+
type: "address",
|
|
2617
|
+
indexed: false,
|
|
2618
|
+
internalType: "address"
|
|
2619
|
+
},
|
|
2595
2620
|
{
|
|
2596
2621
|
name: "group",
|
|
2597
2622
|
type: "bytes32",
|
|
@@ -2777,76 +2802,6 @@ function from$12(parameters) {
|
|
|
2777
2802
|
};
|
|
2778
2803
|
}
|
|
2779
2804
|
|
|
2780
|
-
//#endregion
|
|
2781
|
-
//#region src/core/Quote.ts
|
|
2782
|
-
var Quote_exports = /* @__PURE__ */ __exportAll({
|
|
2783
|
-
InvalidQuoteError: () => InvalidQuoteError,
|
|
2784
|
-
QuoteSchema: () => QuoteSchema,
|
|
2785
|
-
from: () => from$11,
|
|
2786
|
-
fromSnakeCase: () => fromSnakeCase,
|
|
2787
|
-
random: () => random
|
|
2788
|
-
});
|
|
2789
|
-
const QuoteSchema = z$1.object({
|
|
2790
|
-
obligationId: z$1.string().transform(transformHex),
|
|
2791
|
-
ask: z$1.object({ price: z$1.bigint({ coerce: true }).min(0n).max(maxUint256) }),
|
|
2792
|
-
bid: z$1.object({ price: z$1.bigint({ coerce: true }).min(0n).max(maxUint256) })
|
|
2793
|
-
});
|
|
2794
|
-
/**
|
|
2795
|
-
* Creates a quote for a given obligation.
|
|
2796
|
-
* @constructor
|
|
2797
|
-
* @param parameters - {@link from.Parameters}
|
|
2798
|
-
* @returns The created quote. {@link Quote}
|
|
2799
|
-
* @throws If the quote is invalid. {@link InvalidQuoteError}
|
|
2800
|
-
*
|
|
2801
|
-
* @example
|
|
2802
|
-
* ```ts
|
|
2803
|
-
* const quote = Quote.from({ obligationId: "0x123", ask: { price: 100n }, bid: { price: 100n } });
|
|
2804
|
-
* ```
|
|
2805
|
-
*/
|
|
2806
|
-
function from$11(parameters) {
|
|
2807
|
-
try {
|
|
2808
|
-
const parsedQuote = QuoteSchema.parse(parameters);
|
|
2809
|
-
return {
|
|
2810
|
-
obligationId: parsedQuote.obligationId,
|
|
2811
|
-
ask: parsedQuote.ask,
|
|
2812
|
-
bid: parsedQuote.bid
|
|
2813
|
-
};
|
|
2814
|
-
} catch (error) {
|
|
2815
|
-
throw new InvalidQuoteError(error);
|
|
2816
|
-
}
|
|
2817
|
-
}
|
|
2818
|
-
/**
|
|
2819
|
-
* Creates a quote from a snake case object.
|
|
2820
|
-
* @throws If the quote is invalid. {@link InvalidQuoteError}
|
|
2821
|
-
* @param snake - {@link fromSnakeCase.Parameters}
|
|
2822
|
-
* @returns The created quote. {@link fromSnakeCase.ReturnType}
|
|
2823
|
-
*/
|
|
2824
|
-
function fromSnakeCase(snake) {
|
|
2825
|
-
return from$11(fromSnakeCase$3(snake));
|
|
2826
|
-
}
|
|
2827
|
-
/**
|
|
2828
|
-
* Generates a random quote.
|
|
2829
|
-
* @returns A randomly generated quote. {@link random.ReturnType}
|
|
2830
|
-
*
|
|
2831
|
-
* @example
|
|
2832
|
-
* ```ts
|
|
2833
|
-
* const quote = Quote.random();
|
|
2834
|
-
* ```
|
|
2835
|
-
*/
|
|
2836
|
-
function random() {
|
|
2837
|
-
return from$11({
|
|
2838
|
-
obligationId: id(random$2()),
|
|
2839
|
-
ask: { price: BigInt(int(1e6)) },
|
|
2840
|
-
bid: { price: BigInt(int(1e6)) }
|
|
2841
|
-
});
|
|
2842
|
-
}
|
|
2843
|
-
var InvalidQuoteError = class extends BaseError {
|
|
2844
|
-
name = "Quote.InvalidQuoteError";
|
|
2845
|
-
constructor(error) {
|
|
2846
|
-
super("Invalid quote.", { cause: error });
|
|
2847
|
-
}
|
|
2848
|
-
};
|
|
2849
|
-
|
|
2850
2805
|
//#endregion
|
|
2851
2806
|
//#region src/core/Tick.ts
|
|
2852
2807
|
var Tick_exports = /* @__PURE__ */ __exportAll({
|
|
@@ -2926,6 +2881,82 @@ var InvalidPriceError = class extends BaseError {
|
|
|
2926
2881
|
}
|
|
2927
2882
|
};
|
|
2928
2883
|
|
|
2884
|
+
//#endregion
|
|
2885
|
+
//#region src/core/Quote.ts
|
|
2886
|
+
var Quote_exports = /* @__PURE__ */ __exportAll({
|
|
2887
|
+
InvalidQuoteError: () => InvalidQuoteError,
|
|
2888
|
+
from: () => from$11,
|
|
2889
|
+
fromSnakeCase: () => fromSnakeCase,
|
|
2890
|
+
random: () => random
|
|
2891
|
+
});
|
|
2892
|
+
const SideInputSchema = z$1.object({ tick: z$1.number().int().min(0).max(TICK_RANGE).nullable() }).strict();
|
|
2893
|
+
const QuoteInputSchema = z$1.object({
|
|
2894
|
+
obligationId: z$1.string().transform(transformHex),
|
|
2895
|
+
ask: SideInputSchema,
|
|
2896
|
+
bid: SideInputSchema
|
|
2897
|
+
}).strict();
|
|
2898
|
+
/**
|
|
2899
|
+
* Creates a quote for a given obligation.
|
|
2900
|
+
* @constructor
|
|
2901
|
+
* @param parameters - {@link from.Parameters}
|
|
2902
|
+
* @returns The created quote. {@link Quote}
|
|
2903
|
+
* @throws If the quote is invalid. {@link InvalidQuoteError}
|
|
2904
|
+
*
|
|
2905
|
+
* @example
|
|
2906
|
+
* ```ts
|
|
2907
|
+
* const quote = Quote.from({ obligationId: "0x123", ask: { tick: 500 }, bid: { tick: 510 } });
|
|
2908
|
+
* ```
|
|
2909
|
+
*/
|
|
2910
|
+
function from$11(parameters) {
|
|
2911
|
+
try {
|
|
2912
|
+
const parsedQuote = QuoteInputSchema.parse(parameters);
|
|
2913
|
+
return {
|
|
2914
|
+
obligationId: parsedQuote.obligationId,
|
|
2915
|
+
ask: sideFromTick(parsedQuote.ask),
|
|
2916
|
+
bid: sideFromTick(parsedQuote.bid)
|
|
2917
|
+
};
|
|
2918
|
+
} catch (error) {
|
|
2919
|
+
throw new InvalidQuoteError(error);
|
|
2920
|
+
}
|
|
2921
|
+
}
|
|
2922
|
+
/**
|
|
2923
|
+
* Creates a quote from a snake case object.
|
|
2924
|
+
* @throws If the quote is invalid. {@link InvalidQuoteError}
|
|
2925
|
+
* @param snake - {@link fromSnakeCase.Parameters}
|
|
2926
|
+
* @returns The created quote. {@link fromSnakeCase.ReturnType}
|
|
2927
|
+
*/
|
|
2928
|
+
function fromSnakeCase(snake) {
|
|
2929
|
+
return from$11(fromSnakeCase$3(snake));
|
|
2930
|
+
}
|
|
2931
|
+
/**
|
|
2932
|
+
* Generates a random quote.
|
|
2933
|
+
* @returns A randomly generated quote. {@link random.ReturnType}
|
|
2934
|
+
*
|
|
2935
|
+
* @example
|
|
2936
|
+
* ```ts
|
|
2937
|
+
* const quote = Quote.random();
|
|
2938
|
+
* ```
|
|
2939
|
+
*/
|
|
2940
|
+
function random() {
|
|
2941
|
+
return from$11({
|
|
2942
|
+
obligationId: id(random$2()),
|
|
2943
|
+
ask: { tick: int(TICK_RANGE + 1) },
|
|
2944
|
+
bid: { tick: int(TICK_RANGE + 1) }
|
|
2945
|
+
});
|
|
2946
|
+
}
|
|
2947
|
+
var InvalidQuoteError = class extends BaseError {
|
|
2948
|
+
name = "Quote.InvalidQuoteError";
|
|
2949
|
+
constructor(error) {
|
|
2950
|
+
super("Invalid quote.", { cause: error });
|
|
2951
|
+
}
|
|
2952
|
+
};
|
|
2953
|
+
function sideFromTick(side) {
|
|
2954
|
+
return {
|
|
2955
|
+
tick: side.tick,
|
|
2956
|
+
price: side.tick === null ? 0n : tickToPrice(side.tick)
|
|
2957
|
+
};
|
|
2958
|
+
}
|
|
2959
|
+
|
|
2929
2960
|
//#endregion
|
|
2930
2961
|
//#region src/core/TradingFee.ts
|
|
2931
2962
|
var TradingFee_exports = /* @__PURE__ */ __exportAll({
|
|
@@ -3602,6 +3633,7 @@ const offers = s.table(EnumTableName.OFFERS, {
|
|
|
3602
3633
|
buy: boolean("buy").notNull(),
|
|
3603
3634
|
callbackAddress: varchar("callback_address", { length: 42 }).notNull(),
|
|
3604
3635
|
callbackData: text("callback_data").notNull(),
|
|
3636
|
+
receiverIfMakerIsSeller: varchar("receiver_if_maker_is_seller", { length: 42 }),
|
|
3605
3637
|
blockNumber: bigint("block_number", { mode: "number" }).notNull(),
|
|
3606
3638
|
updatedAt: timestamp("updated_at").defaultNow().notNull()
|
|
3607
3639
|
}, (table) => [
|
|
@@ -4983,7 +5015,7 @@ async function* collectPrices(parameters) {
|
|
|
4983
5015
|
//#region src/indexer/collectors/CollectorBuilder.ts
|
|
4984
5016
|
function createBuilder(parameters) {
|
|
4985
5017
|
const { client, db, gatekeeper, options: { maxBlockNumber, blockWindow, interval } = {} } = parameters;
|
|
4986
|
-
const createCollector = (name, collect) => create$
|
|
5018
|
+
const createCollector = (name, collect) => create$20({
|
|
4987
5019
|
name,
|
|
4988
5020
|
collect,
|
|
4989
5021
|
client,
|
|
@@ -5075,7 +5107,7 @@ const from$7 = (parameters) => {
|
|
|
5075
5107
|
//#endregion
|
|
5076
5108
|
//#region src/indexer/Indexer.ts
|
|
5077
5109
|
var Indexer_exports = /* @__PURE__ */ __exportAll({
|
|
5078
|
-
create: () => create$
|
|
5110
|
+
create: () => create$18,
|
|
5079
5111
|
from: () => from$6
|
|
5080
5112
|
});
|
|
5081
5113
|
function from$6(config) {
|
|
@@ -5091,7 +5123,7 @@ function from$6(config) {
|
|
|
5091
5123
|
retryAttempts,
|
|
5092
5124
|
retryDelayMs
|
|
5093
5125
|
});
|
|
5094
|
-
return create$
|
|
5126
|
+
return create$18({
|
|
5095
5127
|
client,
|
|
5096
5128
|
collectors: [
|
|
5097
5129
|
offersCollector,
|
|
@@ -5101,7 +5133,7 @@ function from$6(config) {
|
|
|
5101
5133
|
]
|
|
5102
5134
|
});
|
|
5103
5135
|
}
|
|
5104
|
-
function create$
|
|
5136
|
+
function create$18(params) {
|
|
5105
5137
|
const { collectors, client } = params;
|
|
5106
5138
|
const indexerId = `${client.chain.id.toString()}.indexer`;
|
|
5107
5139
|
const tracer = getTracer(`router.${indexerId}`);
|
|
@@ -5130,12 +5162,12 @@ function create$17(params) {
|
|
|
5130
5162
|
|
|
5131
5163
|
//#endregion
|
|
5132
5164
|
//#region src/api/Health.ts
|
|
5133
|
-
var Health_exports = /* @__PURE__ */ __exportAll({ create: () => create$
|
|
5165
|
+
var Health_exports = /* @__PURE__ */ __exportAll({ create: () => create$17 });
|
|
5134
5166
|
const DEFAULT_MAX_ALLOWED_LAG = 5;
|
|
5135
5167
|
/**
|
|
5136
5168
|
* Create a health service that exposes collector and chain block numbers.
|
|
5137
5169
|
*/
|
|
5138
|
-
function create$
|
|
5170
|
+
function create$17(parameters) {
|
|
5139
5171
|
const { db, maxAllowedLag = DEFAULT_MAX_ALLOWED_LAG, healthClients, chainRegistry } = parameters;
|
|
5140
5172
|
const loadSnapshot = async () => {
|
|
5141
5173
|
const [collectorRows, chainRows, remoteBlockByChainId] = await Promise.all([
|
|
@@ -5299,6 +5331,7 @@ var ObligationResponse_exports = /* @__PURE__ */ __exportAll({ from: () => from$
|
|
|
5299
5331
|
* Creates an `ObligationResponse` from a `Obligation`.
|
|
5300
5332
|
* @constructor
|
|
5301
5333
|
* @param obligation - {@link Obligation}
|
|
5334
|
+
* @param quote - {@link Quote}
|
|
5302
5335
|
* @returns The created `ObligationResponse`. {@link ObligationResponse}
|
|
5303
5336
|
*/
|
|
5304
5337
|
function from$4(obligation, quote) {
|
|
@@ -5312,8 +5345,14 @@ function from$4(obligation, quote) {
|
|
|
5312
5345
|
oracle: c.oracle
|
|
5313
5346
|
})),
|
|
5314
5347
|
maturity: obligation.maturity,
|
|
5315
|
-
ask: {
|
|
5316
|
-
|
|
5348
|
+
ask: {
|
|
5349
|
+
tick: quote.ask.tick,
|
|
5350
|
+
price: quote.ask.price.toString()
|
|
5351
|
+
},
|
|
5352
|
+
bid: {
|
|
5353
|
+
tick: quote.bid.tick,
|
|
5354
|
+
price: quote.bid.price.toString()
|
|
5355
|
+
}
|
|
5317
5356
|
};
|
|
5318
5357
|
}
|
|
5319
5358
|
|
|
@@ -5361,7 +5400,8 @@ function from$3(input) {
|
|
|
5361
5400
|
group: input.group,
|
|
5362
5401
|
session: input.session,
|
|
5363
5402
|
callback: input.callback.address,
|
|
5364
|
-
callback_data: input.callback.data
|
|
5403
|
+
callback_data: input.callback.data,
|
|
5404
|
+
receiver_if_maker_is_seller: input.receiverIfMakerIsSeller
|
|
5365
5405
|
},
|
|
5366
5406
|
offer_hash: input.hash,
|
|
5367
5407
|
obligation_id: id({
|
|
@@ -5428,7 +5468,7 @@ var InternalServerError = class extends APIError {
|
|
|
5428
5468
|
super(STATUS_CODE.INTERNAL_SERVER_ERROR, message, "INTERNAL_SERVER_ERROR");
|
|
5429
5469
|
}
|
|
5430
5470
|
};
|
|
5431
|
-
var BadRequestError = class extends APIError {
|
|
5471
|
+
var BadRequestError$1 = class extends APIError {
|
|
5432
5472
|
constructor(message = "Invalid JSON format", details) {
|
|
5433
5473
|
super(STATUS_CODE.BAD_REQUEST, message, "BAD_REQUEST", details);
|
|
5434
5474
|
}
|
|
@@ -5450,7 +5490,7 @@ function success(args) {
|
|
|
5450
5490
|
*/
|
|
5451
5491
|
function failure(err) {
|
|
5452
5492
|
if (err instanceof APIError) return handleAPIError(err);
|
|
5453
|
-
if (err instanceof SyntaxError) return handleAPIError(new BadRequestError(err.message));
|
|
5493
|
+
if (err instanceof SyntaxError) return handleAPIError(new BadRequestError$1(err.message));
|
|
5454
5494
|
if (err instanceof z$1.ZodError) return handleAPIError(handleZodError(err));
|
|
5455
5495
|
return handleAPIError(new InternalServerError());
|
|
5456
5496
|
}
|
|
@@ -5500,7 +5540,7 @@ function __decorate(decorators, target, key, desc) {
|
|
|
5500
5540
|
//#region src/api/Schema/openapi.ts
|
|
5501
5541
|
const timestampExample = "2024-01-01T12:00:00.000Z";
|
|
5502
5542
|
const offerCursorExample = "eyJvZmZzZXQiOjEwMH0";
|
|
5503
|
-
const obligationCursorExample = "
|
|
5543
|
+
const obligationCursorExample = "eyJzb3J0IjpbImlkIl0sImlkIjoiMHgxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAiLCJhc2siOiIwIiwiYmlkIjoiMCIsIm1hdHVyaXR5IjoxNzYxOTIyODAwfQ";
|
|
5504
5544
|
const offerExample = {
|
|
5505
5545
|
offer: {
|
|
5506
5546
|
obligation: {
|
|
@@ -5523,7 +5563,8 @@ const offerExample = {
|
|
|
5523
5563
|
group: "0x000000000000000000000000000000000000000000000000000000000008b8f4",
|
|
5524
5564
|
session: "0x0000000000000000000000000000000000000000000000000000000000000000",
|
|
5525
5565
|
callback: "0x0000000000000000000000000000000000000000",
|
|
5526
|
-
callback_data: "0x"
|
|
5566
|
+
callback_data: "0x",
|
|
5567
|
+
receiver_if_maker_is_seller: "0x7b093658BE7f90B63D7c359e8f408e503c2D9401"
|
|
5527
5568
|
},
|
|
5528
5569
|
offer_hash: "0xac4bd8318ec914f89f8af913f162230575b0ac0696a19256bc12138c5cfe1427",
|
|
5529
5570
|
obligation_id: "0x25690ae1aee324a005be565f3bcdd16dbf8daf7969b26c181c8b8f467dad9abc",
|
|
@@ -5577,7 +5618,8 @@ const validateOfferExample = {
|
|
|
5577
5618
|
callback: {
|
|
5578
5619
|
address: "0x0000000000000000000000000000000000000000",
|
|
5579
5620
|
data: "0x"
|
|
5580
|
-
}
|
|
5621
|
+
},
|
|
5622
|
+
receiver_if_maker_is_seller: "0x7b093658BE7f90B63D7c359e8f408e503c2D9401"
|
|
5581
5623
|
};
|
|
5582
5624
|
const routerStatusExample = {
|
|
5583
5625
|
status: "live",
|
|
@@ -5648,11 +5690,23 @@ __decorate([ApiProperty({
|
|
|
5648
5690
|
example: validateOfferExample.callback.data
|
|
5649
5691
|
})], ValidateCallbackRequest.prototype, "data", void 0);
|
|
5650
5692
|
var AskResponse = class {};
|
|
5693
|
+
__decorate([ApiProperty({
|
|
5694
|
+
type: "number",
|
|
5695
|
+
nullable: true,
|
|
5696
|
+
example: 500,
|
|
5697
|
+
description: "Best ask tick. Null when there is no active ask quote."
|
|
5698
|
+
})], AskResponse.prototype, "tick", void 0);
|
|
5651
5699
|
__decorate([ApiProperty({
|
|
5652
5700
|
type: "string",
|
|
5653
5701
|
example: "1000000000000000000"
|
|
5654
5702
|
})], AskResponse.prototype, "price", void 0);
|
|
5655
5703
|
var BidResponse = class {};
|
|
5704
|
+
__decorate([ApiProperty({
|
|
5705
|
+
type: "number",
|
|
5706
|
+
nullable: true,
|
|
5707
|
+
example: 500,
|
|
5708
|
+
description: "Best bid tick. Null when there is no active bid quote."
|
|
5709
|
+
})], BidResponse.prototype, "tick", void 0);
|
|
5656
5710
|
__decorate([ApiProperty({
|
|
5657
5711
|
type: "string",
|
|
5658
5712
|
example: "1000000000000000000"
|
|
@@ -5725,6 +5779,10 @@ __decorate([ApiProperty({
|
|
|
5725
5779
|
type: "string",
|
|
5726
5780
|
example: offerExample.offer.callback_data
|
|
5727
5781
|
})], OfferDataResponse.prototype, "callback_data", void 0);
|
|
5782
|
+
__decorate([ApiProperty({
|
|
5783
|
+
type: "string",
|
|
5784
|
+
example: offerExample.offer.receiver_if_maker_is_seller
|
|
5785
|
+
})], OfferDataResponse.prototype, "receiver_if_maker_is_seller", void 0);
|
|
5728
5786
|
var OfferListItemResponse = class {};
|
|
5729
5787
|
__decorate([ApiProperty({
|
|
5730
5788
|
type: () => OfferDataResponse,
|
|
@@ -5994,6 +6052,10 @@ __decorate([ApiProperty({
|
|
|
5994
6052
|
type: () => ValidateCallbackRequest,
|
|
5995
6053
|
example: validateOfferExample.callback
|
|
5996
6054
|
})], ValidateOfferRequest.prototype, "callback", void 0);
|
|
6055
|
+
__decorate([ApiProperty({
|
|
6056
|
+
type: "string",
|
|
6057
|
+
example: validateOfferExample.receiver_if_maker_is_seller
|
|
6058
|
+
})], ValidateOfferRequest.prototype, "receiver_if_maker_is_seller", void 0);
|
|
5997
6059
|
var ValidateOffersRequest = class {};
|
|
5998
6060
|
__decorate([ApiProperty({
|
|
5999
6061
|
type: () => [ValidateOfferRequest],
|
|
@@ -6546,13 +6608,13 @@ __decorate([
|
|
|
6546
6608
|
methods: ["get"],
|
|
6547
6609
|
path: "/v1/obligations",
|
|
6548
6610
|
summary: "List all obligations",
|
|
6549
|
-
description: "Returns a list of obligations with their current best ask and bid.
|
|
6611
|
+
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."
|
|
6550
6612
|
}),
|
|
6551
6613
|
ApiQuery({
|
|
6552
6614
|
name: "cursor",
|
|
6553
6615
|
type: "string",
|
|
6554
6616
|
example: obligationCursorExample,
|
|
6555
|
-
description: "
|
|
6617
|
+
description: "Pagination cursor in base64url-encoded format."
|
|
6556
6618
|
}),
|
|
6557
6619
|
ApiQuery({
|
|
6558
6620
|
name: "limit",
|
|
@@ -6596,6 +6658,15 @@ __decorate([
|
|
|
6596
6658
|
style: "form",
|
|
6597
6659
|
explode: false
|
|
6598
6660
|
}),
|
|
6661
|
+
ApiQuery({
|
|
6662
|
+
name: "sort",
|
|
6663
|
+
type: "string",
|
|
6664
|
+
required: false,
|
|
6665
|
+
example: "-ask,bid,maturity",
|
|
6666
|
+
description: "Sort order as comma-separated fields (`id`, `ask`, `bid`, `maturity`). Prefix with `-` for descending order. Max 3 fields.",
|
|
6667
|
+
style: "form",
|
|
6668
|
+
explode: false
|
|
6669
|
+
}),
|
|
6599
6670
|
ApiResponse({
|
|
6600
6671
|
status: 200,
|
|
6601
6672
|
description: "Success",
|
|
@@ -6731,11 +6802,13 @@ function from$2(position) {
|
|
|
6731
6802
|
//#endregion
|
|
6732
6803
|
//#region src/api/Schema/requests.ts
|
|
6733
6804
|
const MAX_LIMIT = 100;
|
|
6734
|
-
const DEFAULT_LIMIT$
|
|
6805
|
+
const DEFAULT_LIMIT$5 = 20;
|
|
6806
|
+
const MAX_OBLIGATION_SORT_FIELDS = 3;
|
|
6735
6807
|
const CONFIG_RULES_MAX_LIMIT = 1e3;
|
|
6736
6808
|
const CONFIG_RULES_DEFAULT_LIMIT = 100;
|
|
6737
6809
|
const CONFIG_CONTRACTS_MAX_LIMIT = 1e3;
|
|
6738
6810
|
const CONFIG_CONTRACTS_DEFAULT_LIMIT = 1e3;
|
|
6811
|
+
const OBLIGATION_SORT_ENTRY_REGEX = /^-?(id|ask|bid|maturity)$/;
|
|
6739
6812
|
/** Validate cursor is a valid base64url-encoded JSON object.
|
|
6740
6813
|
* Domain layer handles semantic validation of cursor fields. */
|
|
6741
6814
|
function isValidBase64urlJson(val) {
|
|
@@ -6767,8 +6840,8 @@ const PaginationQueryParams = z$1.object({
|
|
|
6767
6840
|
description: "Pagination cursor in base64url-encoded format",
|
|
6768
6841
|
example: "eyJzaWRlIjoic2VsbCIsImN1cnJlbnRQcmljZSI6IjEwMDAwMDAwMDAwMDAwMDAwMDAiLCJibG9ja051bWJlciI6MSwiYXNzZXRzIjoiMTAwMDAwMDAwMDAwMDAwMDAwMCIsImhhc2giOiIweGRmZDY4NTllM2UwODJkMTkzODlhMWFlYzFiZGFkN2U4ZDkyZDk2YjFhYTc5NDBkYTkxYTMxMjVkMzFlM2JlNWIiLCJ0b3RhbFJldHVybmVkIjoxMCwibm93IjoxNjAwMDAwMDAwfQ"
|
|
6769
6842
|
}),
|
|
6770
|
-
limit: z$1.string().regex(/^[1-9]\d*$/, { message: "Limit must be a positive integer" }).transform((val) => Number.parseInt(val, 10)).pipe(z$1.number().max(MAX_LIMIT, { message: `Limit cannot exceed ${MAX_LIMIT}` })).optional().default(DEFAULT_LIMIT$
|
|
6771
|
-
description: `Limit maximum: ${MAX_LIMIT}. Default: ${DEFAULT_LIMIT$
|
|
6843
|
+
limit: z$1.string().regex(/^[1-9]\d*$/, { message: "Limit must be a positive integer" }).transform((val) => Number.parseInt(val, 10)).pipe(z$1.number().max(MAX_LIMIT, { message: `Limit cannot exceed ${MAX_LIMIT}` })).optional().default(DEFAULT_LIMIT$5).meta({
|
|
6844
|
+
description: `Limit maximum: ${MAX_LIMIT}. Default: ${DEFAULT_LIMIT$5}`,
|
|
6772
6845
|
example: 10
|
|
6773
6846
|
})
|
|
6774
6847
|
});
|
|
@@ -6865,9 +6938,12 @@ const GetOffersQueryParams = PaginationQueryParams.omit({ cursor: true }).extend
|
|
|
6865
6938
|
});
|
|
6866
6939
|
const GetObligationsQueryParams = z$1.object({
|
|
6867
6940
|
...PaginationQueryParams.shape,
|
|
6868
|
-
cursor: z$1.string().optional().
|
|
6869
|
-
|
|
6870
|
-
|
|
6941
|
+
cursor: z$1.string().optional().refine((val) => {
|
|
6942
|
+
if (!val) return true;
|
|
6943
|
+
return isValidBase64urlJson(val);
|
|
6944
|
+
}, { message: "Invalid cursor format. Must be a valid base64url-encoded cursor object" }).meta({
|
|
6945
|
+
description: "Pagination cursor in base64url-encoded format.",
|
|
6946
|
+
example: "eyJzb3J0IjpbImlkIl0sImlkIjoiMHgxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAiLCJhc2siOiIwIiwiYmlkIjoiMCIsIm1hdHVyaXR5IjoxNzYxOTIyODAwfQ"
|
|
6871
6947
|
}),
|
|
6872
6948
|
chains: csvArray(z$1.string().regex(/^[1-9]\d*$/, { message: "Chain must be a positive integer" }).transform((val) => Number.parseInt(val, 10))).meta({
|
|
6873
6949
|
description: "Filter by chain IDs (comma-separated).",
|
|
@@ -6884,6 +6960,24 @@ const GetObligationsQueryParams = z$1.object({
|
|
|
6884
6960
|
maturities: csvArray(z$1.string().regex(/^[1-9]\d*$/, { message: "Maturity must be a positive integer" }).transform((val) => Number.parseInt(val, 10))).meta({
|
|
6885
6961
|
description: "Filter by exact maturity timestamps (comma-separated, unix seconds).",
|
|
6886
6962
|
example: "1761922800,1764524800"
|
|
6963
|
+
}),
|
|
6964
|
+
sort: csvArray(z$1.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) => {
|
|
6965
|
+
if (!entries) return;
|
|
6966
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6967
|
+
for (const entry of entries) {
|
|
6968
|
+
const field = entry.startsWith("-") ? entry.slice(1) : entry;
|
|
6969
|
+
if (seen.has(field)) {
|
|
6970
|
+
ctx.addIssue({
|
|
6971
|
+
code: "custom",
|
|
6972
|
+
message: `Duplicate sort field: ${field}`
|
|
6973
|
+
});
|
|
6974
|
+
return;
|
|
6975
|
+
}
|
|
6976
|
+
seen.add(field);
|
|
6977
|
+
}
|
|
6978
|
+
}).meta({
|
|
6979
|
+
description: "Sort order as comma-separated fields. Prefix a field with '-' for descending order. Max 3 fields.",
|
|
6980
|
+
example: "-ask,bid,maturity"
|
|
6887
6981
|
})
|
|
6888
6982
|
});
|
|
6889
6983
|
const GetObligationParams = z$1.object({ obligation_id: z$1.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({
|
|
@@ -6907,8 +7001,8 @@ const BookPaginationQueryParams = z$1.object({
|
|
|
6907
7001
|
description: "Pagination cursor in base64url-encoded format for book levels",
|
|
6908
7002
|
example: "eyJzaWRlIjoiYnV5IiwibGFzdFJhdGUiOiIxMDAwMDAwMDAwMDAwMDAwMDAwIiwib2ZmZXJzQ3Vyc29yIjpudWxsfQ"
|
|
6909
7003
|
}),
|
|
6910
|
-
limit: z$1.string().regex(/^[1-9]\d*$/, { message: "Limit must be a positive integer" }).transform((val) => Number.parseInt(val, 10)).pipe(z$1.number().max(MAX_LIMIT, { message: `Limit cannot exceed ${MAX_LIMIT}` })).optional().default(DEFAULT_LIMIT$
|
|
6911
|
-
description: `Limit maximum: ${MAX_LIMIT}. Default: ${DEFAULT_LIMIT$
|
|
7004
|
+
limit: z$1.string().regex(/^[1-9]\d*$/, { message: "Limit must be a positive integer" }).transform((val) => Number.parseInt(val, 10)).pipe(z$1.number().max(MAX_LIMIT, { message: `Limit cannot exceed ${MAX_LIMIT}` })).optional().default(DEFAULT_LIMIT$5).meta({
|
|
7005
|
+
description: `Limit maximum: ${MAX_LIMIT}. Default: ${DEFAULT_LIMIT$5}`,
|
|
6912
7006
|
example: 10
|
|
6913
7007
|
})
|
|
6914
7008
|
});
|
|
@@ -7085,7 +7179,7 @@ async function getConfigContracts(query, chainRegistry) {
|
|
|
7085
7179
|
}
|
|
7086
7180
|
function parseCursor$1(cursor) {
|
|
7087
7181
|
const [chain, address] = cursor.split(":", 2);
|
|
7088
|
-
if (!chain || !address) throw new BadRequestError("Cursor must be in the format chain_id:0x...");
|
|
7182
|
+
if (!chain || !address) throw new BadRequestError$1("Cursor must be in the format chain_id:0x...");
|
|
7089
7183
|
return {
|
|
7090
7184
|
chain_id: Number.parseInt(chain, 10),
|
|
7091
7185
|
address: address.toLowerCase()
|
|
@@ -7211,19 +7305,19 @@ const oracles = {
|
|
|
7211
7305
|
const configs = {
|
|
7212
7306
|
ethereum: {
|
|
7213
7307
|
callbacks: [{ type: Type$1.BuyWithEmptyCallback }, { type: Type$1.SellWithEmptyCallback }],
|
|
7214
|
-
maturities: [MaturityType.
|
|
7308
|
+
maturities: [MaturityType.EndOfWeek, MaturityType.EndOfNextWeek]
|
|
7215
7309
|
},
|
|
7216
7310
|
base: {
|
|
7217
7311
|
callbacks: [{ type: Type$1.BuyWithEmptyCallback }, { type: Type$1.SellWithEmptyCallback }],
|
|
7218
|
-
maturities: [MaturityType.
|
|
7312
|
+
maturities: [MaturityType.EndOfWeek, MaturityType.EndOfNextWeek]
|
|
7219
7313
|
},
|
|
7220
7314
|
"ethereum-virtual-testnet": {
|
|
7221
7315
|
callbacks: [{ type: Type$1.BuyWithEmptyCallback }, { type: Type$1.SellWithEmptyCallback }],
|
|
7222
|
-
maturities: [MaturityType.
|
|
7316
|
+
maturities: [MaturityType.EndOfWeek, MaturityType.EndOfNextWeek]
|
|
7223
7317
|
},
|
|
7224
7318
|
anvil: {
|
|
7225
7319
|
callbacks: [{ type: Type$1.BuyWithEmptyCallback }, { type: Type$1.SellWithEmptyCallback }],
|
|
7226
|
-
maturities: [MaturityType.
|
|
7320
|
+
maturities: [MaturityType.EndOfWeek, MaturityType.EndOfNextWeek]
|
|
7227
7321
|
}
|
|
7228
7322
|
};
|
|
7229
7323
|
|
|
@@ -7338,8 +7432,8 @@ async function getConfigRules(query, chains) {
|
|
|
7338
7432
|
} catch (err) {
|
|
7339
7433
|
return failure(err);
|
|
7340
7434
|
}
|
|
7341
|
-
if (cursorRule && typeFilter && !typeFilter.has(cursorRule.type)) return failure(new BadRequestError("Cursor type must match requested rule types"));
|
|
7342
|
-
if (cursorRule && chainFilter && !chainFilter.has(cursorRule.chain_id)) return failure(new BadRequestError("Cursor chain_id must match requested chains"));
|
|
7435
|
+
if (cursorRule && typeFilter && !typeFilter.has(cursorRule.type)) return failure(new BadRequestError$1("Cursor type must match requested rule types"));
|
|
7436
|
+
if (cursorRule && chainFilter && !chainFilter.has(cursorRule.chain_id)) return failure(new BadRequestError$1("Cursor chain_id must match requested chains"));
|
|
7343
7437
|
const startIndex = cursorRule ? findStartIndex(filteredRules, cursorRule) : 0;
|
|
7344
7438
|
const page = filteredRules.slice(startIndex, startIndex + limit);
|
|
7345
7439
|
const nextCursor = startIndex + limit < filteredRules.length && page.length > 0 ? formatCursor(page.at(-1)) : null;
|
|
@@ -7359,15 +7453,15 @@ function formatCursor(rule) {
|
|
|
7359
7453
|
}
|
|
7360
7454
|
function parseCursor(cursor) {
|
|
7361
7455
|
const [type, chain, ...rest] = cursor.split(":");
|
|
7362
|
-
if (!type || !chain || rest.length === 0) throw new BadRequestError("Cursor must be in the format type:chain_id:<value>");
|
|
7363
|
-
if (!isConfigRuleType(type)) throw new BadRequestError("Cursor has an invalid rule type");
|
|
7456
|
+
if (!type || !chain || rest.length === 0) throw new BadRequestError$1("Cursor must be in the format type:chain_id:<value>");
|
|
7457
|
+
if (!isConfigRuleType(type)) throw new BadRequestError$1("Cursor has an invalid rule type");
|
|
7364
7458
|
const chain_id = Number.parseInt(chain, 10);
|
|
7365
|
-
if (!Number.isFinite(chain_id)) throw new BadRequestError("Cursor has an invalid chain_id");
|
|
7459
|
+
if (!Number.isFinite(chain_id)) throw new BadRequestError$1("Cursor has an invalid chain_id");
|
|
7366
7460
|
if (type === "maturity") {
|
|
7367
7461
|
const timestampValue = Number.parseInt(rest[0] ?? "", 10);
|
|
7368
7462
|
const nameValue = rest.slice(1).join(":");
|
|
7369
|
-
if (!Number.isFinite(timestampValue) || nameValue.length === 0) throw new BadRequestError("Cursor must be in the format maturity:chain_id:timestamp:name");
|
|
7370
|
-
if (!isMaturityType(nameValue)) throw new BadRequestError("Cursor has an invalid maturity name");
|
|
7463
|
+
if (!Number.isFinite(timestampValue) || nameValue.length === 0) throw new BadRequestError$1("Cursor must be in the format maturity:chain_id:timestamp:name");
|
|
7464
|
+
if (!isMaturityType(nameValue)) throw new BadRequestError$1("Cursor has an invalid maturity name");
|
|
7371
7465
|
return {
|
|
7372
7466
|
type,
|
|
7373
7467
|
chain_id,
|
|
@@ -7378,8 +7472,8 @@ function parseCursor(cursor) {
|
|
|
7378
7472
|
if (type === "callback") {
|
|
7379
7473
|
const callbackTypeValue = rest[0] ?? "";
|
|
7380
7474
|
const addressValue = rest.slice(1).join(":");
|
|
7381
|
-
if (!callbackTypeValue || !addressValue) throw new BadRequestError("Cursor must be in the format callback:chain_id:callback_type:address");
|
|
7382
|
-
if (!isCallbackType(callbackTypeValue)) throw new BadRequestError("Cursor has an invalid callback type");
|
|
7475
|
+
if (!callbackTypeValue || !addressValue) throw new BadRequestError$1("Cursor must be in the format callback:chain_id:callback_type:address");
|
|
7476
|
+
if (!isCallbackType(callbackTypeValue)) throw new BadRequestError$1("Cursor has an invalid callback type");
|
|
7383
7477
|
return {
|
|
7384
7478
|
type,
|
|
7385
7479
|
chain_id,
|
|
@@ -7389,14 +7483,14 @@ function parseCursor(cursor) {
|
|
|
7389
7483
|
}
|
|
7390
7484
|
if (type === "loan_token" || type === "collateral_token" || type === "oracle") {
|
|
7391
7485
|
const addressValue = rest.join(":");
|
|
7392
|
-
if (!addressValue) throw new BadRequestError(`Cursor must be in the format ${type}:chain_id:address`);
|
|
7486
|
+
if (!addressValue) throw new BadRequestError$1(`Cursor must be in the format ${type}:chain_id:address`);
|
|
7393
7487
|
return {
|
|
7394
7488
|
type,
|
|
7395
7489
|
chain_id,
|
|
7396
7490
|
address: parseAddress(addressValue, "Cursor address")
|
|
7397
7491
|
};
|
|
7398
7492
|
}
|
|
7399
|
-
throw new BadRequestError("Cursor has an invalid rule type");
|
|
7493
|
+
throw new BadRequestError$1("Cursor has an invalid rule type");
|
|
7400
7494
|
}
|
|
7401
7495
|
function findStartIndex(rules, cursor) {
|
|
7402
7496
|
let low = 0;
|
|
@@ -7410,7 +7504,7 @@ function findStartIndex(rules, cursor) {
|
|
|
7410
7504
|
return low;
|
|
7411
7505
|
}
|
|
7412
7506
|
function parseAddress(address, label) {
|
|
7413
|
-
if (!/^0x[a-fA-F0-9]{40}$/.test(address)) throw new BadRequestError(`${label} must be a valid 20-byte address`);
|
|
7507
|
+
if (!/^0x[a-fA-F0-9]{40}$/.test(address)) throw new BadRequestError$1(`${label} must be a valid 20-byte address`);
|
|
7414
7508
|
return address.toLowerCase();
|
|
7415
7509
|
}
|
|
7416
7510
|
function isConfigRuleType(value) {
|
|
@@ -7423,7 +7517,7 @@ function parseMaturity(value) {
|
|
|
7423
7517
|
try {
|
|
7424
7518
|
return from$16(value);
|
|
7425
7519
|
} catch (err) {
|
|
7426
|
-
throw new BadRequestError(err instanceof Error ? err.message : "Invalid maturity timestamp");
|
|
7520
|
+
throw new BadRequestError$1(err instanceof Error ? err.message : "Invalid maturity timestamp");
|
|
7427
7521
|
}
|
|
7428
7522
|
}
|
|
7429
7523
|
function isCallbackType(value) {
|
|
@@ -7519,7 +7613,7 @@ async function getHealth(query, db, chainRegistry) {
|
|
|
7519
7613
|
try {
|
|
7520
7614
|
const parsed = safeParse("get_health", query);
|
|
7521
7615
|
if (!parsed.success) return failure(parsed.error);
|
|
7522
|
-
const snapshot = await create$
|
|
7616
|
+
const snapshot = await create$17({
|
|
7523
7617
|
db,
|
|
7524
7618
|
chainRegistry
|
|
7525
7619
|
}).getSnapshot();
|
|
@@ -7548,7 +7642,7 @@ async function getHealthChains(query, db, healthClients, chainRegistry) {
|
|
|
7548
7642
|
try {
|
|
7549
7643
|
const parsed = safeParse("get_health_chains", query);
|
|
7550
7644
|
if (!parsed.success) return failure(parsed.error);
|
|
7551
|
-
const snapshot = await create$
|
|
7645
|
+
const snapshot = await create$17({
|
|
7552
7646
|
db,
|
|
7553
7647
|
healthClients,
|
|
7554
7648
|
chainRegistry
|
|
@@ -7580,7 +7674,7 @@ async function getHealthCollectors(query, db, chainRegistry) {
|
|
|
7580
7674
|
try {
|
|
7581
7675
|
const parsed = safeParse("get_health_collectors", query);
|
|
7582
7676
|
if (!parsed.success) return failure(parsed.error);
|
|
7583
|
-
const snapshot = await create$
|
|
7677
|
+
const snapshot = await create$17({
|
|
7584
7678
|
db,
|
|
7585
7679
|
chainRegistry
|
|
7586
7680
|
}).getSnapshot();
|
|
@@ -7609,39 +7703,274 @@ async function getHealthCollectors(query, db, chainRegistry) {
|
|
|
7609
7703
|
}
|
|
7610
7704
|
}
|
|
7611
7705
|
|
|
7706
|
+
//#endregion
|
|
7707
|
+
//#region src/database/readers/ObligationsListing.ts
|
|
7708
|
+
const SORT_FIELDS = [
|
|
7709
|
+
"id",
|
|
7710
|
+
"ask",
|
|
7711
|
+
"bid",
|
|
7712
|
+
"maturity"
|
|
7713
|
+
];
|
|
7714
|
+
const CURSOR_ID_REGEX = /^0x[a-f0-9]{64}$/i;
|
|
7715
|
+
const INT32_MIN = -2147483648;
|
|
7716
|
+
const INT32_MAX = 2147483647;
|
|
7717
|
+
const INT32_MAX_BIGINT = BigInt(INT32_MAX);
|
|
7718
|
+
const MAX_CURSOR_SORT_FIELDS = 4;
|
|
7719
|
+
const DEFAULT_LIMIT$4 = 20;
|
|
7720
|
+
var BadRequestError = class extends Error {
|
|
7721
|
+
constructor(message) {
|
|
7722
|
+
super(message);
|
|
7723
|
+
this.name = "ObligationsListingBadRequestError";
|
|
7724
|
+
}
|
|
7725
|
+
};
|
|
7726
|
+
/**
|
|
7727
|
+
* Creates the obligations listing reader facade.
|
|
7728
|
+
* @param parameters - Reader dependencies.
|
|
7729
|
+
* @returns Obligations listing reader.
|
|
7730
|
+
*/
|
|
7731
|
+
function create$16(parameters) {
|
|
7732
|
+
const { db } = parameters;
|
|
7733
|
+
return { list: async (queryParameters) => {
|
|
7734
|
+
const { ids, chainId: chainIds, loanToken: loanTokens, collateralToken: collateralTokens, maturity: maturities, sort: sortTokens, cursor: encodedCursor, limit: requestedLimit } = queryParameters ?? {};
|
|
7735
|
+
const limit = requestedLimit ?? DEFAULT_LIMIT$4;
|
|
7736
|
+
if (!Number.isInteger(limit) || limit <= 0) throw new BadRequestError("Limit must be a positive integer");
|
|
7737
|
+
const cursorPayload = encodedCursor ? decodeCursorPayload(encodedCursor) : void 0;
|
|
7738
|
+
const requestedSort = normalizeSort(sortTokens);
|
|
7739
|
+
const cursorSort = cursorPayload ? normalizeSort(cursorPayload.sort) : void 0;
|
|
7740
|
+
if (cursorSort !== void 0 && sortTokens !== void 0 && !hasSameSort(requestedSort, cursorSort)) throw new BadRequestError("Cursor sort does not match requested sort");
|
|
7741
|
+
const sort = sortTokens !== void 0 ? requestedSort : cursorSort ?? requestedSort;
|
|
7742
|
+
const cursorValues = cursorPayload ? cursorValuesFromPayload(cursorPayload) : void 0;
|
|
7743
|
+
const now$3 = now();
|
|
7744
|
+
const loanTokenFilter = loanTokens !== void 0 && loanTokens.length > 0 ? sql`(${sql.join(loanTokens.map((token) => sql`LOWER(${obligations.loanToken}) = ${token.toLowerCase()}`), sql` OR `)})` : void 0;
|
|
7745
|
+
const collateralFilter = collateralTokens !== void 0 && collateralTokens.length > 0 ? sql`EXISTS (
|
|
7746
|
+
SELECT 1 FROM ${obligationCollateralsV2} oc
|
|
7747
|
+
WHERE oc.obligation_id = ${obligations.obligationId}
|
|
7748
|
+
AND (${sql.join(collateralTokens.map((token) => sql`LOWER(oc.asset) = ${token.toLowerCase()}`), sql` OR `)})
|
|
7749
|
+
)` : void 0;
|
|
7750
|
+
const bestAskTick = db.select({ askTick: offers.tick }).from(offers).innerJoin(groups, and(eq(offers.groupChainId, groups.chainId), eq(offers.groupMaker, groups.maker), eq(offers.group, groups.group))).leftJoin(validations, eq(offers.hash, validations.offerHash)).leftJoin(status, eq(validations.statusId, status.id)).where(and(eq(offers.obligationId, obligations.obligationId), eq(offers.buy, false), gte(offers.expiry, now$3), gte(offers.maturity, now$3), lte(offers.start, now$3), sql`(${status.code} IS NULL OR ${status.code} = ${Status.VALID})`)).orderBy(desc(offers.tick)).limit(1).as("best_ask_tick");
|
|
7751
|
+
const bestBidTick = db.select({ bidTick: offers.tick }).from(offers).innerJoin(groups, and(eq(offers.groupChainId, groups.chainId), eq(offers.groupMaker, groups.maker), eq(offers.group, groups.group))).leftJoin(validations, eq(offers.hash, validations.offerHash)).leftJoin(status, eq(validations.statusId, status.id)).where(and(eq(offers.obligationId, obligations.obligationId), eq(offers.buy, true), gte(offers.expiry, now$3), gte(offers.maturity, now$3), lte(offers.start, now$3), sql`(${status.code} IS NULL OR ${status.code} = ${Status.VALID})`)).orderBy(asc(offers.tick)).limit(1).as("best_bid_tick");
|
|
7752
|
+
const obligationsWithQuotes = db.select({
|
|
7753
|
+
obligationId: obligations.obligationId,
|
|
7754
|
+
chainId: obligations.chainId,
|
|
7755
|
+
loanToken: obligations.loanToken,
|
|
7756
|
+
collaterals: sql`ARRAY_AGG(jsonb_build_object('asset', ${obligationCollateralsV2.asset}, 'oracle', ${oracles$1.address}, 'lltv', ${obligationCollateralsV2.lltv}))`.as("collaterals"),
|
|
7757
|
+
maturity: obligations.maturity,
|
|
7758
|
+
askTick: sql`MAX(${bestAskTick.askTick})`.as("ask_tick"),
|
|
7759
|
+
bidTick: sql`MAX(${bestBidTick.bidTick})`.as("bid_tick"),
|
|
7760
|
+
ask: sql`COALESCE(MAX(${bestAskTick.askTick}) + 1, 0)`.as("ask"),
|
|
7761
|
+
bid: sql`COALESCE(MAX(${bestBidTick.bidTick}) + 1, 0)`.as("bid")
|
|
7762
|
+
}).from(obligations).innerJoin(obligationCollateralsV2, eq(obligations.obligationId, obligationCollateralsV2.obligationId)).innerJoin(oracles$1, sql`${obligationCollateralsV2.oracleChainId} = ${oracles$1.chainId}
|
|
7763
|
+
AND ${obligationCollateralsV2.oracleAddress} = ${oracles$1.address}`).leftJoinLateral(bestAskTick, sql`true`).leftJoinLateral(bestBidTick, sql`true`).groupBy(obligations.obligationId).where(and(ids !== void 0 && ids.length > 0 ? inArray(obligations.obligationId, ids) : void 0, chainIds !== void 0 && chainIds.length > 0 ? inArray(obligations.chainId, chainIds) : void 0, loanTokenFilter, maturities !== void 0 && maturities.length > 0 ? inArray(obligations.maturity, maturities) : gte(obligations.maturity, now$3), collateralFilter)).as("obligations_with_quotes");
|
|
7764
|
+
const sortColumns = {
|
|
7765
|
+
id: obligationsWithQuotes.obligationId,
|
|
7766
|
+
ask: obligationsWithQuotes.ask,
|
|
7767
|
+
bid: obligationsWithQuotes.bid,
|
|
7768
|
+
maturity: obligationsWithQuotes.maturity
|
|
7769
|
+
};
|
|
7770
|
+
const rows = await db.select({
|
|
7771
|
+
obligationId: obligationsWithQuotes.obligationId,
|
|
7772
|
+
chainId: obligationsWithQuotes.chainId,
|
|
7773
|
+
loanToken: obligationsWithQuotes.loanToken,
|
|
7774
|
+
collaterals: obligationsWithQuotes.collaterals,
|
|
7775
|
+
maturity: obligationsWithQuotes.maturity,
|
|
7776
|
+
askTick: obligationsWithQuotes.askTick,
|
|
7777
|
+
bidTick: obligationsWithQuotes.bidTick,
|
|
7778
|
+
ask: obligationsWithQuotes.ask,
|
|
7779
|
+
bid: obligationsWithQuotes.bid
|
|
7780
|
+
}).from(obligationsWithQuotes).where(buildCursorFilter(sortColumns, sort, cursorValues)).orderBy(...buildOrderBy(sortColumns, sort)).limit(limit + 1);
|
|
7781
|
+
const hasMore = rows.length > limit;
|
|
7782
|
+
const listedRows = (hasMore ? rows.slice(0, limit) : rows).map((row) => {
|
|
7783
|
+
return {
|
|
7784
|
+
obligation: from$15({
|
|
7785
|
+
chainId: row.chainId,
|
|
7786
|
+
loanToken: row.loanToken,
|
|
7787
|
+
collaterals: row.collaterals.sort((left, right) => left.asset.localeCompare(right.asset)).map((collateral) => from$17({
|
|
7788
|
+
asset: collateral.asset,
|
|
7789
|
+
oracle: collateral.oracle,
|
|
7790
|
+
lltv: from$18(BigInt(collateral.lltv))
|
|
7791
|
+
})),
|
|
7792
|
+
maturity: row.maturity
|
|
7793
|
+
}),
|
|
7794
|
+
quote: from$11({
|
|
7795
|
+
obligationId: row.obligationId,
|
|
7796
|
+
ask: { tick: row.askTick },
|
|
7797
|
+
bid: { tick: row.bidTick }
|
|
7798
|
+
}),
|
|
7799
|
+
cursorValues: {
|
|
7800
|
+
id: row.obligationId,
|
|
7801
|
+
ask: toBigInt(row.ask),
|
|
7802
|
+
bid: toBigInt(row.bid),
|
|
7803
|
+
maturity: row.maturity
|
|
7804
|
+
}
|
|
7805
|
+
};
|
|
7806
|
+
});
|
|
7807
|
+
const nextCursor = hasMore && listedRows.length > 0 ? encodeCursorPayload({
|
|
7808
|
+
sort: sortToTokens(sort),
|
|
7809
|
+
id: listedRows[listedRows.length - 1].cursorValues.id,
|
|
7810
|
+
ask: listedRows[listedRows.length - 1].cursorValues.ask.toString(),
|
|
7811
|
+
bid: listedRows[listedRows.length - 1].cursorValues.bid.toString(),
|
|
7812
|
+
maturity: listedRows[listedRows.length - 1].cursorValues.maturity
|
|
7813
|
+
}) : null;
|
|
7814
|
+
return {
|
|
7815
|
+
obligations: listedRows.map((row) => ({
|
|
7816
|
+
obligation: row.obligation,
|
|
7817
|
+
quote: row.quote
|
|
7818
|
+
})),
|
|
7819
|
+
nextCursor
|
|
7820
|
+
};
|
|
7821
|
+
} };
|
|
7822
|
+
}
|
|
7823
|
+
function isSortField(value) {
|
|
7824
|
+
return SORT_FIELDS.includes(value);
|
|
7825
|
+
}
|
|
7826
|
+
function parseSortToken(token) {
|
|
7827
|
+
const direction = token.startsWith("-") ? "desc" : "asc";
|
|
7828
|
+
const rawField = token.startsWith("-") ? token.slice(1) : token;
|
|
7829
|
+
if (!isSortField(rawField)) throw new BadRequestError(`Invalid sort field: ${rawField}`);
|
|
7830
|
+
return {
|
|
7831
|
+
field: rawField,
|
|
7832
|
+
direction
|
|
7833
|
+
};
|
|
7834
|
+
}
|
|
7835
|
+
function normalizeSort(sortTokens) {
|
|
7836
|
+
const parsed = sortTokens?.length ? sortTokens.map(parseSortToken) : [{
|
|
7837
|
+
field: "id",
|
|
7838
|
+
direction: "asc"
|
|
7839
|
+
}];
|
|
7840
|
+
return parsed.some((entry) => entry.field === "id") ? parsed : [...parsed, {
|
|
7841
|
+
field: "id",
|
|
7842
|
+
direction: "asc"
|
|
7843
|
+
}];
|
|
7844
|
+
}
|
|
7845
|
+
function sortToTokens(sortEntries) {
|
|
7846
|
+
return sortEntries.map((entry) => entry.direction === "desc" ? `-${entry.field}` : entry.field);
|
|
7847
|
+
}
|
|
7848
|
+
function hasSameSort(left, right) {
|
|
7849
|
+
if (left.length !== right.length) return false;
|
|
7850
|
+
return left.every((sortEntry, index) => sortEntry.field === right[index]?.field && sortEntry.direction === right[index]?.direction);
|
|
7851
|
+
}
|
|
7852
|
+
function decodeCursorPayload(cursor) {
|
|
7853
|
+
let decoded;
|
|
7854
|
+
try {
|
|
7855
|
+
decoded = JSON.parse(Buffer.from(cursor, "base64url").toString("utf8"));
|
|
7856
|
+
} catch {
|
|
7857
|
+
throw new BadRequestError("Invalid cursor format");
|
|
7858
|
+
}
|
|
7859
|
+
if (decoded === null || typeof decoded !== "object") throw new BadRequestError("Invalid cursor payload");
|
|
7860
|
+
const payload = decoded;
|
|
7861
|
+
const sortTokens = parseCursorSortTokens(payload.sort);
|
|
7862
|
+
if (typeof payload.id !== "string" || !CURSOR_ID_REGEX.test(payload.id)) throw new BadRequestError("Invalid cursor obligation id");
|
|
7863
|
+
const ask = parseCursorNonNegativeInt32(payload.ask, "ask");
|
|
7864
|
+
const bid = parseCursorNonNegativeInt32(payload.bid, "bid");
|
|
7865
|
+
if (!isInt32(payload.maturity)) throw new BadRequestError("Invalid cursor maturity value");
|
|
7866
|
+
return {
|
|
7867
|
+
sort: sortTokens,
|
|
7868
|
+
id: payload.id,
|
|
7869
|
+
ask,
|
|
7870
|
+
bid,
|
|
7871
|
+
maturity: payload.maturity
|
|
7872
|
+
};
|
|
7873
|
+
}
|
|
7874
|
+
function parseCursorSortTokens(value) {
|
|
7875
|
+
if (!Array.isArray(value) || value.length === 0 || value.length > MAX_CURSOR_SORT_FIELDS) throw new BadRequestError("Invalid cursor sort");
|
|
7876
|
+
const sortEntries = value.map((token) => {
|
|
7877
|
+
if (typeof token !== "string") throw new BadRequestError("Invalid cursor sort");
|
|
7878
|
+
try {
|
|
7879
|
+
return parseSortToken(token);
|
|
7880
|
+
} catch {
|
|
7881
|
+
throw new BadRequestError("Invalid cursor sort");
|
|
7882
|
+
}
|
|
7883
|
+
});
|
|
7884
|
+
if (new Set(sortEntries.map((entry) => entry.field)).size !== sortEntries.length) throw new BadRequestError("Invalid cursor sort");
|
|
7885
|
+
return sortToTokens(sortEntries);
|
|
7886
|
+
}
|
|
7887
|
+
function parseCursorNonNegativeInt32(value, field) {
|
|
7888
|
+
if (typeof value !== "string" || !/^\d+$/.test(value)) throw new BadRequestError(`Invalid cursor ${field} value`);
|
|
7889
|
+
if (BigInt(value) > INT32_MAX_BIGINT) throw new BadRequestError(`Invalid cursor ${field} value`);
|
|
7890
|
+
return value;
|
|
7891
|
+
}
|
|
7892
|
+
function isInt32(value) {
|
|
7893
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= INT32_MIN && value <= INT32_MAX;
|
|
7894
|
+
}
|
|
7895
|
+
function encodeCursorPayload(payload) {
|
|
7896
|
+
return Buffer.from(JSON.stringify(payload), "utf8").toString("base64url");
|
|
7897
|
+
}
|
|
7898
|
+
function cursorValuesFromPayload(payload) {
|
|
7899
|
+
return {
|
|
7900
|
+
id: payload.id,
|
|
7901
|
+
ask: BigInt(payload.ask),
|
|
7902
|
+
bid: BigInt(payload.bid),
|
|
7903
|
+
maturity: payload.maturity
|
|
7904
|
+
};
|
|
7905
|
+
}
|
|
7906
|
+
function cursorComparisonValue(cursorValues, field) {
|
|
7907
|
+
switch (field) {
|
|
7908
|
+
case "id": return cursorValues.id;
|
|
7909
|
+
case "maturity": return cursorValues.maturity;
|
|
7910
|
+
case "ask": return cursorValues.ask.toString();
|
|
7911
|
+
case "bid": return cursorValues.bid.toString();
|
|
7912
|
+
}
|
|
7913
|
+
}
|
|
7914
|
+
function buildCursorFilter(columns, sortEntries, cursorValues) {
|
|
7915
|
+
if (cursorValues === void 0) return void 0;
|
|
7916
|
+
const comparisons = sortEntries.map((sortEntry, index) => {
|
|
7917
|
+
const equals = sortEntries.slice(0, index).map((previous) => {
|
|
7918
|
+
return sql`${columns[previous.field]} = ${cursorComparisonValue(cursorValues, previous.field)}`;
|
|
7919
|
+
});
|
|
7920
|
+
const comparison = sortEntry.direction === "asc" ? sql`${columns[sortEntry.field]} > ${cursorComparisonValue(cursorValues, sortEntry.field)}` : sql`${columns[sortEntry.field]} < ${cursorComparisonValue(cursorValues, sortEntry.field)}`;
|
|
7921
|
+
return equals.length > 0 ? sql`(${sql.join([...equals, comparison], sql` AND `)})` : sql`(${comparison})`;
|
|
7922
|
+
});
|
|
7923
|
+
return comparisons.length > 0 ? sql`(${sql.join(comparisons, sql` OR `)})` : void 0;
|
|
7924
|
+
}
|
|
7925
|
+
function buildOrderBy(columns, sortEntries) {
|
|
7926
|
+
return sortEntries.map((sortEntry) => sortEntry.direction === "asc" ? asc(columns[sortEntry.field]) : desc(columns[sortEntry.field]));
|
|
7927
|
+
}
|
|
7928
|
+
function toBigInt(value) {
|
|
7929
|
+
if (typeof value === "bigint") return value;
|
|
7930
|
+
if (typeof value === "number") return BigInt(value);
|
|
7931
|
+
return BigInt(value.split(".")[0] ?? "0");
|
|
7932
|
+
}
|
|
7933
|
+
|
|
7612
7934
|
//#endregion
|
|
7613
7935
|
//#region src/api/Controllers/getObligation.ts
|
|
7936
|
+
function toPayloadError$1(err) {
|
|
7937
|
+
if (err instanceof BadRequestError) return new BadRequestError$1(err.message);
|
|
7938
|
+
return err;
|
|
7939
|
+
}
|
|
7614
7940
|
async function getObligation(params, db) {
|
|
7615
7941
|
const logger = getLogger();
|
|
7616
7942
|
const result = safeParse("get_obligation", params, (issue) => issue.message);
|
|
7617
7943
|
if (!result.success) return failure(result.error);
|
|
7618
7944
|
const query = result.data;
|
|
7619
7945
|
try {
|
|
7620
|
-
const
|
|
7621
|
-
|
|
7622
|
-
|
|
7623
|
-
|
|
7946
|
+
const listing = await db.readers.obligations.list({
|
|
7947
|
+
ids: [query.obligation_id],
|
|
7948
|
+
limit: 1
|
|
7949
|
+
});
|
|
7950
|
+
if (listing.obligations.length === 0) return failure(new NotFoundError("Obligation not found"));
|
|
7951
|
+
const obligation = listing.obligations[0];
|
|
7624
7952
|
return success({
|
|
7625
|
-
data: from$4(obligation, quote
|
|
7626
|
-
obligationId: id(obligation),
|
|
7627
|
-
ask: { price: 0n },
|
|
7628
|
-
bid: { price: 0n }
|
|
7629
|
-
}),
|
|
7953
|
+
data: from$4(obligation.obligation, obligation.quote),
|
|
7630
7954
|
cursor: null
|
|
7631
7955
|
});
|
|
7632
7956
|
} catch (err) {
|
|
7957
|
+
const payloadError = toPayloadError$1(err);
|
|
7633
7958
|
logger.error({
|
|
7634
|
-
err,
|
|
7959
|
+
err: payloadError,
|
|
7635
7960
|
msg: "Error get obligation",
|
|
7636
|
-
errorMessage:
|
|
7637
|
-
errorStack:
|
|
7961
|
+
errorMessage: payloadError instanceof Error ? payloadError.message : String(payloadError),
|
|
7962
|
+
errorStack: payloadError instanceof Error ? payloadError.stack : void 0
|
|
7638
7963
|
});
|
|
7639
|
-
return failure(
|
|
7964
|
+
return failure(payloadError);
|
|
7640
7965
|
}
|
|
7641
7966
|
}
|
|
7642
7967
|
|
|
7643
7968
|
//#endregion
|
|
7644
7969
|
//#region src/api/Controllers/getObligations.ts
|
|
7970
|
+
function toPayloadError(err) {
|
|
7971
|
+
if (err instanceof BadRequestError) return new BadRequestError$1(err.message);
|
|
7972
|
+
return err;
|
|
7973
|
+
}
|
|
7645
7974
|
async function getObligations$1(queryParameters, db) {
|
|
7646
7975
|
const logger = getLogger();
|
|
7647
7976
|
const result = safeParse("get_obligations", queryParameters, (issue) => issue.message);
|
|
@@ -7652,31 +7981,28 @@ async function getObligations$1(queryParameters, db) {
|
|
|
7652
7981
|
const loanTokens = query.loan_tokens?.length ? query.loan_tokens : void 0;
|
|
7653
7982
|
const collateralTokens = query.collateral_tokens?.length ? query.collateral_tokens : void 0;
|
|
7654
7983
|
const maturities = query.maturities?.length ? query.maturities : void 0;
|
|
7655
|
-
const
|
|
7656
|
-
cursor: query.cursor,
|
|
7657
|
-
limit: query.limit,
|
|
7984
|
+
const listing = await db.readers.obligations.list({
|
|
7658
7985
|
chainId: chainIds,
|
|
7659
7986
|
loanToken: loanTokens,
|
|
7660
7987
|
collateralToken: collateralTokens,
|
|
7661
|
-
maturity: maturities
|
|
7988
|
+
maturity: maturities,
|
|
7989
|
+
sort: query.sort,
|
|
7990
|
+
cursor: query.cursor,
|
|
7991
|
+
limit: query.limit
|
|
7662
7992
|
});
|
|
7663
|
-
const quotes = await db.offers.getQuotes({ obligationIds: obligations.map((o) => id(o)) });
|
|
7664
7993
|
return success({
|
|
7665
|
-
data: obligations.map((
|
|
7666
|
-
|
|
7667
|
-
ask: { price: 0n },
|
|
7668
|
-
bid: { price: 0n }
|
|
7669
|
-
})),
|
|
7670
|
-
cursor: nextCursor ?? null
|
|
7994
|
+
data: listing.obligations.map((item) => from$4(item.obligation, item.quote)),
|
|
7995
|
+
cursor: listing.nextCursor
|
|
7671
7996
|
});
|
|
7672
7997
|
} catch (err) {
|
|
7998
|
+
const payloadError = toPayloadError(err);
|
|
7673
7999
|
logger.error({
|
|
7674
|
-
err,
|
|
8000
|
+
err: payloadError,
|
|
7675
8001
|
msg: "Error get obligations",
|
|
7676
|
-
errorMessage:
|
|
7677
|
-
errorStack:
|
|
8002
|
+
errorMessage: payloadError instanceof Error ? payloadError.message : String(payloadError),
|
|
8003
|
+
errorStack: payloadError instanceof Error ? payloadError.stack : void 0
|
|
7678
8004
|
});
|
|
7679
|
-
return failure(
|
|
8005
|
+
return failure(payloadError);
|
|
7680
8006
|
}
|
|
7681
8007
|
}
|
|
7682
8008
|
|
|
@@ -7710,6 +8036,7 @@ function create$15(config) {
|
|
|
7710
8036
|
groupMaker: offer.maker.toLowerCase(),
|
|
7711
8037
|
callbackAddress: offer.callback.address.toLowerCase(),
|
|
7712
8038
|
callbackData: offer.callback.data,
|
|
8039
|
+
receiverIfMakerIsSeller: offer.receiverIfMakerIsSeller.toLowerCase(),
|
|
7713
8040
|
blockNumber
|
|
7714
8041
|
})));
|
|
7715
8042
|
if (offersRows.length === 0) return [];
|
|
@@ -7772,9 +8099,11 @@ function create$15(config) {
|
|
|
7772
8099
|
loanToken: obligations.loanToken,
|
|
7773
8100
|
callbackAddress: offers.callbackAddress,
|
|
7774
8101
|
callbackData: offers.callbackData,
|
|
8102
|
+
receiverIfMakerIsSeller: offers.receiverIfMakerIsSeller,
|
|
7775
8103
|
collaterals: collateralsLateral.collaterals,
|
|
7776
8104
|
blockNumber: offers.blockNumber
|
|
7777
8105
|
}).from(offers).innerJoin(obligations, eq(offers.obligationId, obligations.obligationId)).innerJoinLateral(collateralsLateral, sql`true`).where(and(cursor !== null && cursor !== void 0 ? gt(offers.hash, cursor) : void 0, maker !== void 0 ? eq(offers.groupMaker, maker.toLowerCase()) : void 0)).orderBy(asc(offers.hash)).limit(limit)).map((row) => {
|
|
8106
|
+
const receiverIfMakerIsSeller = (row.receiverIfMakerIsSeller ?? row.maker).toLowerCase();
|
|
7778
8107
|
return {
|
|
7779
8108
|
hash: row.hash,
|
|
7780
8109
|
maker: row.maker,
|
|
@@ -7799,6 +8128,7 @@ function create$15(config) {
|
|
|
7799
8128
|
address: row.callbackAddress,
|
|
7800
8129
|
data: row.callbackData
|
|
7801
8130
|
},
|
|
8131
|
+
receiverIfMakerIsSeller,
|
|
7802
8132
|
consumed: 0n,
|
|
7803
8133
|
available: 0n,
|
|
7804
8134
|
takeable: 0n,
|
|
@@ -7823,64 +8153,30 @@ function create$15(config) {
|
|
|
7823
8153
|
}
|
|
7824
8154
|
throw new Error("Invalid parameters");
|
|
7825
8155
|
},
|
|
7826
|
-
getObligations: async (parameters) => {
|
|
7827
|
-
const { ids, chainId: chainIds, loanToken: loanTokens, collateralToken: collateralTokens, maturity: maturities, cursor, limit = DEFAULT_LIMIT$3 } = parameters ?? {};
|
|
7828
|
-
const now$1 = now();
|
|
7829
|
-
const loanTokenFilter = loanTokens !== void 0 && loanTokens.length > 0 ? sql`(${sql.join(loanTokens.map((token) => sql`LOWER(${obligations.loanToken}) = ${token.toLowerCase()}`), sql` OR `)})` : void 0;
|
|
7830
|
-
const collateralFilter = collateralTokens !== void 0 && collateralTokens.length > 0 ? sql`EXISTS (
|
|
7831
|
-
SELECT 1 FROM ${obligationCollateralsV2} oc
|
|
7832
|
-
WHERE oc.obligation_id = ${obligations.obligationId}
|
|
7833
|
-
AND (${sql.join(collateralTokens.map((token) => sql`LOWER(oc.asset) = ${token.toLowerCase()}`), sql` OR `)})
|
|
7834
|
-
)` : void 0;
|
|
7835
|
-
const result = await db.select({
|
|
7836
|
-
obligationId: obligations.obligationId,
|
|
7837
|
-
chainId: obligations.chainId,
|
|
7838
|
-
loanToken: obligations.loanToken,
|
|
7839
|
-
collaterals: sql`ARRAY_AGG(jsonb_build_object('asset', ${obligationCollateralsV2.asset}, 'oracle', ${oracles$1.address}, 'lltv', ${obligationCollateralsV2.lltv}))`.as("collaterals"),
|
|
7840
|
-
maturity: obligations.maturity
|
|
7841
|
-
}).from(obligations).innerJoin(obligationCollateralsV2, eq(obligations.obligationId, obligationCollateralsV2.obligationId)).innerJoin(oracles$1, sql`${obligationCollateralsV2.oracleChainId} = ${oracles$1.chainId}
|
|
7842
|
-
AND ${obligationCollateralsV2.oracleAddress} = ${oracles$1.address}`).groupBy(obligations.obligationId).where(and(cursor !== null && cursor !== void 0 ? gt(obligations.obligationId, cursor) : sql`true`, ids !== void 0 && ids.length > 0 ? inArray(obligations.obligationId, ids) : void 0, chainIds !== void 0 && chainIds.length > 0 ? inArray(obligations.chainId, chainIds) : void 0, loanTokenFilter, maturities !== void 0 && maturities.length > 0 ? inArray(obligations.maturity, maturities) : gte(obligations.maturity, now$1), collateralFilter)).orderBy(asc(obligations.obligationId)).limit(limit);
|
|
7843
|
-
const items = [];
|
|
7844
|
-
for (const row of result) items.push(from$15({
|
|
7845
|
-
chainId: row.chainId,
|
|
7846
|
-
loanToken: row.loanToken,
|
|
7847
|
-
collaterals: row.collaterals.sort((a, b) => a.asset.localeCompare(b.asset)).map((c) => from$17({
|
|
7848
|
-
asset: c.asset,
|
|
7849
|
-
oracle: c.oracle,
|
|
7850
|
-
lltv: from$18(BigInt(c.lltv))
|
|
7851
|
-
})),
|
|
7852
|
-
maturity: row.maturity
|
|
7853
|
-
}));
|
|
7854
|
-
const returnedItems = Array.from(items.values());
|
|
7855
|
-
return {
|
|
7856
|
-
obligations: returnedItems,
|
|
7857
|
-
nextCursor: returnedItems.length === limit && returnedItems.length > 0 ? result[result.length - 1].obligationId : null
|
|
7858
|
-
};
|
|
7859
|
-
},
|
|
7860
8156
|
getQuotes: async (parameters) => {
|
|
7861
8157
|
const { obligationIds } = parameters;
|
|
7862
8158
|
if (obligationIds.length === 0) return [];
|
|
7863
8159
|
const now$2 = now();
|
|
7864
8160
|
const query = ({ side }) => db.selectDistinctOn([offers.obligationId], {
|
|
7865
8161
|
obligationId: offers.obligationId,
|
|
7866
|
-
|
|
8162
|
+
tick: offers.tick
|
|
7867
8163
|
}).from(offers).innerJoin(groups, and(eq(offers.groupChainId, groups.chainId), eq(offers.groupMaker, groups.maker), eq(offers.group, groups.group))).leftJoin(validations, eq(offers.hash, validations.offerHash)).leftJoin(status, eq(validations.statusId, status.id)).where(and(inArray(offers.obligationId, obligationIds), eq(offers.buy, side === "buy"), gte(offers.expiry, now$2), gte(offers.maturity, now$2), lte(offers.start, now$2), sql`(${status.code} IS NULL OR ${status.code} = ${Status.VALID})`)).orderBy(offers.obligationId, side === "buy" ? sql`${offers.tick} ASC` : sql`${offers.tick} DESC`);
|
|
7868
8164
|
const [bestBuys, bestSells] = await Promise.all([query({ side: "buy" }), query({ side: "sell" })]);
|
|
7869
8165
|
const quotes = /* @__PURE__ */ new Map();
|
|
7870
8166
|
for (const row of bestSells) quotes.set(row.obligationId, {
|
|
7871
|
-
ask: {
|
|
7872
|
-
bid: {
|
|
8167
|
+
ask: { tick: row.tick },
|
|
8168
|
+
bid: { tick: null }
|
|
7873
8169
|
});
|
|
7874
8170
|
for (const row of bestBuys) {
|
|
7875
8171
|
const quote = quotes.get(row.obligationId);
|
|
7876
8172
|
if (!quote) {
|
|
7877
8173
|
quotes.set(row.obligationId, {
|
|
7878
|
-
ask: {
|
|
7879
|
-
bid: {
|
|
8174
|
+
ask: { tick: null },
|
|
8175
|
+
bid: { tick: row.tick }
|
|
7880
8176
|
});
|
|
7881
8177
|
continue;
|
|
7882
8178
|
}
|
|
7883
|
-
quote.bid = {
|
|
8179
|
+
quote.bid = { tick: row.tick };
|
|
7884
8180
|
}
|
|
7885
8181
|
return Array.from(quotes.entries()).map(([id, quote]) => {
|
|
7886
8182
|
return from$11({
|
|
@@ -7991,6 +8287,7 @@ async function getOffersQuery(db, parameters) {
|
|
|
7991
8287
|
loanToken: obligations.loanToken,
|
|
7992
8288
|
callbackAddress: offers.callbackAddress,
|
|
7993
8289
|
callbackData: offers.callbackData,
|
|
8290
|
+
receiverIfMakerIsSeller: offers.receiverIfMakerIsSeller,
|
|
7994
8291
|
collaterals: collateralsLateral.collaterals,
|
|
7995
8292
|
blockNumber: offers.blockNumber,
|
|
7996
8293
|
available: sql`${availableExpr}::numeric`.as("available"),
|
|
@@ -8012,6 +8309,7 @@ async function getOffersQuery(db, parameters) {
|
|
|
8012
8309
|
)
|
|
8013
8310
|
END
|
|
8014
8311
|
) > 0` : void 0)).orderBy(asc(offers.hash)).limit(limit)).map((row) => {
|
|
8312
|
+
const receiverIfMakerIsSeller = (row.receiverIfMakerIsSeller ?? row.maker).toLowerCase();
|
|
8015
8313
|
return {
|
|
8016
8314
|
hash: row.hash,
|
|
8017
8315
|
maker: row.maker,
|
|
@@ -8036,6 +8334,7 @@ async function getOffersQuery(db, parameters) {
|
|
|
8036
8334
|
address: row.callbackAddress,
|
|
8037
8335
|
data: row.callbackData
|
|
8038
8336
|
},
|
|
8337
|
+
receiverIfMakerIsSeller,
|
|
8039
8338
|
consumed: BigInt(row.consumed),
|
|
8040
8339
|
available: BigInt(String(row.available ?? "0").split(".")[0] ?? "0"),
|
|
8041
8340
|
takeable: BigInt(String(row.takeable ?? "0").split(".")[0] ?? "0"),
|
|
@@ -8126,7 +8425,7 @@ async function getUserPositions(queryParameters, db) {
|
|
|
8126
8425
|
async function validateOffers(body, gatekeeper) {
|
|
8127
8426
|
const logger = getLogger();
|
|
8128
8427
|
const result = safeParse("validate_offers", body, (issue) => issue.message);
|
|
8129
|
-
if (!result.success) return failure(new BadRequestError(result.error.issues[0]?.message ?? "Invalid request body"));
|
|
8428
|
+
if (!result.success) return failure(new BadRequestError$1(result.error.issues[0]?.message ?? "Invalid request body"));
|
|
8130
8429
|
const { offers: rawOffers } = result.data;
|
|
8131
8430
|
const parsedOffers = [];
|
|
8132
8431
|
const offerIndexByHash = /* @__PURE__ */ new Map();
|
|
@@ -8142,7 +8441,7 @@ async function validateOffers(body, gatekeeper) {
|
|
|
8142
8441
|
} catch (err) {
|
|
8143
8442
|
let message = err instanceof Error ? err.message : String(err);
|
|
8144
8443
|
if (err instanceof InvalidOfferError) message = err.formattedMessage;
|
|
8145
|
-
return failure(new BadRequestError(`Offer at index ${i} failed to parse: ${message}`));
|
|
8444
|
+
return failure(new BadRequestError$1(`Offer at index ${i} failed to parse: ${message}`));
|
|
8146
8445
|
}
|
|
8147
8446
|
}
|
|
8148
8447
|
try {
|
|
@@ -8434,7 +8733,8 @@ async function getOffers(apiClient, parameters) {
|
|
|
8434
8733
|
callback: {
|
|
8435
8734
|
address: offerData.callback,
|
|
8436
8735
|
data: offerData.callback_data
|
|
8437
|
-
}
|
|
8736
|
+
},
|
|
8737
|
+
receiver_if_maker_is_seller: offerData.receiver_if_maker_is_seller
|
|
8438
8738
|
}),
|
|
8439
8739
|
hash: item.offer_hash,
|
|
8440
8740
|
consumed: BigInt(item.consumed),
|
|
@@ -8451,13 +8751,15 @@ async function getOffers(apiClient, parameters) {
|
|
|
8451
8751
|
};
|
|
8452
8752
|
}
|
|
8453
8753
|
async function getObligations(apiClient, parameters) {
|
|
8754
|
+
const sort = parameters?.sort?.length ? parameters.sort.join(",") : void 0;
|
|
8454
8755
|
const { data, error, response } = await apiClient.GET("/v1/obligations", { params: { query: {
|
|
8455
8756
|
cursor: parameters?.cursor,
|
|
8456
8757
|
limit: parameters?.limit,
|
|
8457
8758
|
chains: parameters?.chainIds,
|
|
8458
8759
|
loan_tokens: parameters?.loanTokens,
|
|
8459
8760
|
collateral_tokens: parameters?.collateralTokens,
|
|
8460
|
-
maturities: parameters?.maturities
|
|
8761
|
+
maturities: parameters?.maturities,
|
|
8762
|
+
sort
|
|
8461
8763
|
} } });
|
|
8462
8764
|
if (error !== void 0) {
|
|
8463
8765
|
switch (response.status) {
|
|
@@ -8481,10 +8783,10 @@ async function getObligations(apiClient, parameters) {
|
|
|
8481
8783
|
const { obligationId: _, ...returned } = {
|
|
8482
8784
|
id: () => id(obligation),
|
|
8483
8785
|
...obligation,
|
|
8484
|
-
...
|
|
8485
|
-
|
|
8486
|
-
ask: item.ask,
|
|
8487
|
-
bid: item.bid
|
|
8786
|
+
...from$11({
|
|
8787
|
+
obligationId: item.id,
|
|
8788
|
+
ask: { tick: item.ask.tick },
|
|
8789
|
+
bid: { tick: item.bid.tick }
|
|
8488
8790
|
})
|
|
8489
8791
|
};
|
|
8490
8792
|
return returned;
|
|
@@ -8940,6 +9242,7 @@ async function _getOffers(db, params) {
|
|
|
8940
9242
|
p.buy,
|
|
8941
9243
|
p.callback_address,
|
|
8942
9244
|
p.callback_data,
|
|
9245
|
+
p.receiver_if_maker_is_seller,
|
|
8943
9246
|
p.block_number,
|
|
8944
9247
|
p.group_chain_id,
|
|
8945
9248
|
p.group_maker,
|
|
@@ -9017,6 +9320,7 @@ async function _getOffers(db, params) {
|
|
|
9017
9320
|
buy,
|
|
9018
9321
|
callback_address,
|
|
9019
9322
|
callback_data,
|
|
9323
|
+
receiver_if_maker_is_seller,
|
|
9020
9324
|
block_number,
|
|
9021
9325
|
group_chain_id,
|
|
9022
9326
|
group_maker,
|
|
@@ -9034,8 +9338,8 @@ async function _getOffers(db, params) {
|
|
|
9034
9338
|
ORDER BY clc.hash, clc.position_chain_id, clc.position_contract, clc.position_user, clc.contribution_in_loan DESC
|
|
9035
9339
|
) deduped
|
|
9036
9340
|
GROUP BY hash, obligation_id, assets, tick, obligation_units, obligation_shares, maturity, expiry, start, group_group, buy,
|
|
9037
|
-
|
|
9038
|
-
consumed, chain_id, loan_token, session
|
|
9341
|
+
callback_address, callback_data, block_number, group_chain_id, group_maker,
|
|
9342
|
+
consumed, chain_id, loan_token, session, receiver_if_maker_is_seller
|
|
9039
9343
|
UNION ALL
|
|
9040
9344
|
-- Sell offers without callbacks: collateral positions not indexed, takeable = assets - consumed
|
|
9041
9345
|
SELECT
|
|
@@ -9043,6 +9347,7 @@ async function _getOffers(db, params) {
|
|
|
9043
9347
|
p.obligation_units, p.obligation_shares,
|
|
9044
9348
|
p.maturity, p.expiry, p.start, p.group_group,
|
|
9045
9349
|
p.buy, p.callback_address, p.callback_data,
|
|
9350
|
+
p.receiver_if_maker_is_seller,
|
|
9046
9351
|
p.block_number, p.group_chain_id, p.group_maker,
|
|
9047
9352
|
p.consumed, p.chain_id, p.loan_token, p.session,
|
|
9048
9353
|
0 AS total_available
|
|
@@ -9071,6 +9376,7 @@ async function _getOffers(db, params) {
|
|
|
9071
9376
|
oc.loan_token,
|
|
9072
9377
|
oc.callback_address,
|
|
9073
9378
|
oc.callback_data,
|
|
9379
|
+
oc.receiver_if_maker_is_seller,
|
|
9074
9380
|
oc.block_number,
|
|
9075
9381
|
oc.session,
|
|
9076
9382
|
COALESCE(oc.total_available, 0) AS available,
|
|
@@ -9100,6 +9406,7 @@ async function _getOffers(db, params) {
|
|
|
9100
9406
|
`);
|
|
9101
9407
|
return {
|
|
9102
9408
|
rows: raw.rows.map((row) => {
|
|
9409
|
+
const receiverIfMakerIsSeller = (row.receiver_if_maker_is_seller ?? row.group_maker).toLowerCase();
|
|
9103
9410
|
return {
|
|
9104
9411
|
hash: row.hash,
|
|
9105
9412
|
maker: row.group_maker,
|
|
@@ -9124,6 +9431,7 @@ async function _getOffers(db, params) {
|
|
|
9124
9431
|
address: row.callback_address,
|
|
9125
9432
|
data: row.callback_data
|
|
9126
9433
|
},
|
|
9434
|
+
receiverIfMakerIsSeller,
|
|
9127
9435
|
blockNumber: row.block_number,
|
|
9128
9436
|
consumed: BigInt(row.consumed ?? 0),
|
|
9129
9437
|
available: BigInt(String(row.available ?? "0").split(".")[0] ?? "0"),
|
|
@@ -9373,38 +9681,60 @@ function create$8(db) {
|
|
|
9373
9681
|
* @returns Obligations domain. {@link ObligationsDomain}
|
|
9374
9682
|
*/
|
|
9375
9683
|
function create$7(db) {
|
|
9376
|
-
return {
|
|
9377
|
-
|
|
9378
|
-
|
|
9379
|
-
|
|
9380
|
-
|
|
9381
|
-
|
|
9382
|
-
|
|
9383
|
-
|
|
9384
|
-
|
|
9385
|
-
|
|
9386
|
-
|
|
9387
|
-
|
|
9388
|
-
|
|
9389
|
-
|
|
9390
|
-
|
|
9391
|
-
|
|
9392
|
-
|
|
9393
|
-
|
|
9684
|
+
return {
|
|
9685
|
+
get: async (parameters) => {
|
|
9686
|
+
const chainIds = parameters?.chainId;
|
|
9687
|
+
const now$1 = now();
|
|
9688
|
+
return (await db.select({
|
|
9689
|
+
chainId: obligations.chainId,
|
|
9690
|
+
loanToken: obligations.loanToken,
|
|
9691
|
+
collaterals: sql`ARRAY_AGG(jsonb_build_object('asset', ${obligationCollateralsV2.asset}, 'oracle', ${oracles$1.address}, 'lltv', ${obligationCollateralsV2.lltv}))`.as("collaterals"),
|
|
9692
|
+
maturity: obligations.maturity
|
|
9693
|
+
}).from(obligations).innerJoin(obligationCollateralsV2, eq(obligations.obligationId, obligationCollateralsV2.obligationId)).innerJoin(oracles$1, sql`${obligationCollateralsV2.oracleChainId} = ${oracles$1.chainId}
|
|
9694
|
+
AND ${obligationCollateralsV2.oracleAddress} = ${oracles$1.address}`).groupBy(obligations.obligationId).where(and(chainIds !== void 0 && chainIds.length > 0 ? inArray(obligations.chainId, chainIds) : void 0, gte(obligations.maturity, now$1))).orderBy(asc(obligations.obligationId))).map((row) => from$15({
|
|
9695
|
+
chainId: row.chainId,
|
|
9696
|
+
loanToken: row.loanToken,
|
|
9697
|
+
collaterals: row.collaterals.sort((left, right) => left.asset.localeCompare(right.asset)).map((collateral) => from$17({
|
|
9698
|
+
asset: collateral.asset,
|
|
9699
|
+
oracle: collateral.oracle,
|
|
9700
|
+
lltv: from$18(BigInt(collateral.lltv))
|
|
9701
|
+
})),
|
|
9702
|
+
maturity: row.maturity
|
|
9703
|
+
}));
|
|
9704
|
+
},
|
|
9705
|
+
create: async (obligations$1) => {
|
|
9706
|
+
if (obligations$1.length === 0) return;
|
|
9707
|
+
const obligationsById = /* @__PURE__ */ new Map();
|
|
9708
|
+
for (const obligation of obligations$1) {
|
|
9709
|
+
const id$1 = id(obligation).toLowerCase();
|
|
9710
|
+
if (!obligationsById.get(id$1)) obligationsById.set(id$1, obligation);
|
|
9711
|
+
}
|
|
9712
|
+
try {
|
|
9713
|
+
await db.transaction(async (dbTx) => {
|
|
9714
|
+
const obligationRows = obligations$1.map((obligation) => ({
|
|
9394
9715
|
obligationId: id(obligation),
|
|
9395
|
-
|
|
9396
|
-
|
|
9397
|
-
|
|
9398
|
-
lltv: collateral.lltv
|
|
9716
|
+
chainId: obligation.chainId,
|
|
9717
|
+
loanToken: obligation.loanToken.toLowerCase(),
|
|
9718
|
+
maturity: obligation.maturity
|
|
9399
9719
|
}));
|
|
9720
|
+
for (const batch of batch$1(obligationRows, DEFAULT_BATCH_SIZE$1)) await dbTx.insert(obligations).values(batch).onConflictDoNothing();
|
|
9721
|
+
const collateralRows = obligations$1.flatMap((obligation) => {
|
|
9722
|
+
return obligation.collaterals.map((collateral) => ({
|
|
9723
|
+
obligationId: id(obligation),
|
|
9724
|
+
asset: collateral.asset.toLowerCase(),
|
|
9725
|
+
oracleChainId: obligation.chainId,
|
|
9726
|
+
oracleAddress: collateral.oracle.toLowerCase(),
|
|
9727
|
+
lltv: collateral.lltv
|
|
9728
|
+
}));
|
|
9729
|
+
});
|
|
9730
|
+
for (const batch of batch$1(collateralRows, DEFAULT_BATCH_SIZE$1)) await dbTx.insert(obligationCollateralsV2).values(batch).onConflictDoNothing();
|
|
9400
9731
|
});
|
|
9401
|
-
|
|
9402
|
-
|
|
9403
|
-
|
|
9404
|
-
|
|
9405
|
-
throw new Error("Obligations.create failed. Ensure oracles exist before inserting obligations.", { cause: error });
|
|
9732
|
+
} catch (err) {
|
|
9733
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
9734
|
+
throw new Error("Obligations.create failed. Ensure oracles exist before inserting obligations.", { cause: error });
|
|
9735
|
+
}
|
|
9406
9736
|
}
|
|
9407
|
-
}
|
|
9737
|
+
};
|
|
9408
9738
|
}
|
|
9409
9739
|
|
|
9410
9740
|
//#endregion
|
|
@@ -9989,6 +10319,9 @@ function createDomains(core, chainRegistry) {
|
|
|
9989
10319
|
transfers: create$3(core)
|
|
9990
10320
|
};
|
|
9991
10321
|
}
|
|
10322
|
+
function createReaders(core) {
|
|
10323
|
+
return { obligations: create$16({ db: core }) };
|
|
10324
|
+
}
|
|
9992
10325
|
const AUGMENT_CACHE = /* @__PURE__ */ new WeakMap();
|
|
9993
10326
|
function augmentWithDomains(base, chainRegistry) {
|
|
9994
10327
|
const cached = AUGMENT_CACHE.get(base)?.get(chainRegistry);
|
|
@@ -10000,6 +10333,7 @@ function augmentWithDomains(base, chainRegistry) {
|
|
|
10000
10333
|
});
|
|
10001
10334
|
};
|
|
10002
10335
|
const dms = createDomains(wrapped, chainRegistry);
|
|
10336
|
+
const readers = createReaders(wrapped);
|
|
10003
10337
|
Object.defineProperties(wrapped, {
|
|
10004
10338
|
book: {
|
|
10005
10339
|
value: dms.book,
|
|
@@ -10056,6 +10390,10 @@ function augmentWithDomains(base, chainRegistry) {
|
|
|
10056
10390
|
transfers: {
|
|
10057
10391
|
value: dms.transfers,
|
|
10058
10392
|
enumerable: true
|
|
10393
|
+
},
|
|
10394
|
+
readers: {
|
|
10395
|
+
value: readers,
|
|
10396
|
+
enumerable: true
|
|
10059
10397
|
}
|
|
10060
10398
|
});
|
|
10061
10399
|
const chainRegistryMap = AUGMENT_CACHE.get(base);
|
|
@@ -10695,7 +11033,7 @@ const chains = ({ chains }) => single("chain_ids", `Validates that offer chain i
|
|
|
10695
11033
|
});
|
|
10696
11034
|
const maturity = ({ maturities }) => single("maturity", `Validates that offer maturity is one of: [${maturities.join(", ")}]`, (offer) => {
|
|
10697
11035
|
const allowedMaturities = maturities.map((m) => from$16(m));
|
|
10698
|
-
if (!allowedMaturities.includes(offer.maturity)) return { message: `Maturity must be
|
|
11036
|
+
if (!allowedMaturities.includes(offer.maturity)) return { message: `Maturity must be one of (${allowedMaturities.join(", ")}). Got: ${offer.maturity}` };
|
|
10699
11037
|
});
|
|
10700
11038
|
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) => {
|
|
10701
11039
|
if (!isEmptyCallback(offer)) return { message: "Non-empty callbacks are not supported." };
|
|
@@ -10775,7 +11113,7 @@ const morphoRules = (chains$3) => {
|
|
|
10775
11113
|
sameMaker(),
|
|
10776
11114
|
amountMutualExclusivity(),
|
|
10777
11115
|
chains({ chains: chains$3 }),
|
|
10778
|
-
maturity({ maturities: [MaturityType.
|
|
11116
|
+
maturity({ maturities: [MaturityType.EndOfWeek, MaturityType.EndOfNextWeek] }),
|
|
10779
11117
|
callback({
|
|
10780
11118
|
callbacks: [Type$1.BuyWithEmptyCallback, Type$1.SellWithEmptyCallback],
|
|
10781
11119
|
allowedAddresses: []
|