@morpho-dev/router 0.12.0 → 0.12.1
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 +799 -316
- package/dist/drizzle/migrations/0050_contract-sync-v1.16.sql +305 -0
- package/dist/drizzle/migrations/meta/0050_snapshot.json +2035 -0
- package/dist/drizzle/migrations/meta/_journal.json +7 -0
- package/dist/evm/bytecode/morpho.txt +1 -1
- package/dist/index.browser.d.mts +60 -47
- package/dist/index.browser.d.mts.map +1 -1
- package/dist/index.browser.mjs +127 -77
- package/dist/index.browser.mjs.map +1 -1
- package/dist/index.node.d.mts +130 -90
- package/dist/index.node.d.mts.map +1 -1
- package/dist/index.node.mjs +733 -314
- package/dist/index.node.mjs.map +1 -1
- package/dist/{server-D4xxddev.js → server-DNFuP89-.js} +1 -1
- package/dist/server.js +1 -1
- package/package.json +1 -1
package/dist/index.node.mjs
CHANGED
|
@@ -93,7 +93,7 @@ const MorphoV2 = parseAbi([
|
|
|
93
93
|
"function obligationCreated(bytes32 id) view returns (bool)",
|
|
94
94
|
"function obligationState(bytes32 id) view returns (uint128 totalUnits, uint256 withdrawable, uint128 lossIndex, bool created)",
|
|
95
95
|
"function owner() view returns (address)",
|
|
96
|
-
"function repay((address loanToken, (address token, uint256 lltv, uint256 maxLif, address oracle)[] collaterals, uint256 maturity, uint256 rcfThreshold) obligation, uint256
|
|
96
|
+
"function repay((address loanToken, (address token, uint256 lltv, uint256 maxLif, address oracle)[] collaterals, uint256 maturity, uint256 rcfThreshold) obligation, uint256 units, address onBehalf)",
|
|
97
97
|
"function session(address user) view returns (bytes32)",
|
|
98
98
|
"function setConsumed(bytes32 group, uint256 amount, address onBehalf)",
|
|
99
99
|
"function setDefaultTradingFee(address loanToken, uint256 index, uint256 newTradingFee)",
|
|
@@ -108,7 +108,7 @@ const MorphoV2 = parseAbi([
|
|
|
108
108
|
"function shuffleSession(address onBehalf)",
|
|
109
109
|
"function slash(bytes32 id, address user)",
|
|
110
110
|
"function supplyCollateral((address loanToken, (address token, uint256 lltv, uint256 maxLif, address oracle)[] collaterals, uint256 maturity, uint256 rcfThreshold) obligation, uint256 collateralIndex, uint256 assets, address onBehalf)",
|
|
111
|
-
"function take(uint256
|
|
111
|
+
"function take(uint256 units, address taker, address takerCallback, bytes takerCallbackData, address receiverIfTakerIsSeller, ((address loanToken, (address token, uint256 lltv, uint256 maxLif, address oracle)[] collaterals, uint256 maturity, uint256 rcfThreshold) obligation, bool buy, address maker, uint256 maxUnits, uint256 start, uint256 expiry, uint256 tick, bytes32 group, bytes32 session, address callback, bytes callbackData, address receiverIfMakerIsSeller, bool exitOnly) offer, (uint8 v, bytes32 r, bytes32 s) sig, bytes32 root, bytes32[] proof) returns (uint256, uint256, uint256)",
|
|
112
112
|
"function toId((address loanToken, (address token, uint256 lltv, uint256 maxLif, address oracle)[] collaterals, uint256 maturity, uint256 rcfThreshold) obligation) view returns (bytes32)",
|
|
113
113
|
"function toObligation(bytes32 id) view returns ((address loanToken, (address token, uint256 lltv, uint256 maxLif, address oracle)[] collaterals, uint256 maturity, uint256 rcfThreshold))",
|
|
114
114
|
"function totalUnits(bytes32 id) view returns (uint256)",
|
|
@@ -116,14 +116,14 @@ const MorphoV2 = parseAbi([
|
|
|
116
116
|
"function tradingFee(bytes32 id, uint256 timeToMaturity) view returns (uint256)",
|
|
117
117
|
"function tradingFeeRecipient() view returns (address)",
|
|
118
118
|
"function userLossIndex(bytes32 id, address user) view returns (uint128)",
|
|
119
|
-
"function withdraw((address loanToken, (address token, uint256 lltv, uint256 maxLif, address oracle)[] collaterals, uint256 maturity, uint256 rcfThreshold) obligation, uint256
|
|
119
|
+
"function withdraw((address loanToken, (address token, uint256 lltv, uint256 maxLif, address oracle)[] collaterals, uint256 maturity, uint256 rcfThreshold) obligation, uint256 units, address onBehalf, address receiver)",
|
|
120
120
|
"function withdrawCollateral((address loanToken, (address token, uint256 lltv, uint256 maxLif, address oracle)[] collaterals, uint256 maturity, uint256 rcfThreshold) obligation, uint256 collateralIndex, uint256 assets, address onBehalf, address receiver)",
|
|
121
121
|
"function withdrawable(bytes32 id) view returns (uint256)",
|
|
122
122
|
"event Constructor(address indexed owner)",
|
|
123
123
|
"event FlashLoan(address indexed caller, address indexed token, uint256 assets)",
|
|
124
124
|
"event Liquidate(address indexed caller, bytes32 indexed id_, uint256 collateralIndex, uint256 seizedAssets, uint256 repaidUnits, address indexed borrower, uint256 badDebt, uint256 latestLossIndex)",
|
|
125
125
|
"event ObligationCreated(bytes32 indexed id_, (address loanToken, (address token, uint256 lltv, uint256 maxLif, address oracle)[] collaterals, uint256 maturity, uint256 rcfThreshold) obligation)",
|
|
126
|
-
"event Repay(address indexed caller, bytes32 indexed id_, uint256
|
|
126
|
+
"event Repay(address indexed caller, bytes32 indexed id_, uint256 units, address indexed onBehalf)",
|
|
127
127
|
"event SetConsumed(address indexed caller, address indexed onBehalf, bytes32 indexed group, uint256 amount)",
|
|
128
128
|
"event SetDefaultTradingFee(address indexed loanToken, uint256 indexed index, uint256 newTradingFee)",
|
|
129
129
|
"event SetFeeSetter(address indexed feeSetter)",
|
|
@@ -137,8 +137,8 @@ const MorphoV2 = parseAbi([
|
|
|
137
137
|
"event ShuffleSession(address indexed caller, address indexed onBehalf, bytes32 session)",
|
|
138
138
|
"event Slash(address caller, bytes32 indexed id_, address indexed user, uint256 credit, uint256 latestLossIndex)",
|
|
139
139
|
"event SupplyCollateral(address caller, bytes32 indexed id_, address indexed collateral, uint256 assets, address indexed onBehalf)",
|
|
140
|
-
"event Take(address caller, bytes32 indexed id_, address indexed maker, address indexed taker, bool offerIsBuy, uint256 buyerAssets, uint256 sellerAssets, uint256
|
|
141
|
-
"event Withdraw(address caller, bytes32 indexed id_, uint256
|
|
140
|
+
"event Take(address caller, bytes32 indexed id_, address indexed maker, address indexed taker, bool offerIsBuy, uint256 buyerAssets, uint256 sellerAssets, uint256 units, address sellerReceiver, bytes32 group, uint256 consumed, uint256 totalUnits)",
|
|
141
|
+
"event Withdraw(address caller, bytes32 indexed id_, uint256 units, address indexed onBehalf, address indexed receiver)",
|
|
142
142
|
"event WithdrawCollateral(address caller, bytes32 indexed id_, address indexed collateral, uint256 assets, address indexed onBehalf, address receiver)"
|
|
143
143
|
]);
|
|
144
144
|
|
|
@@ -489,8 +489,8 @@ const chains$1 = {
|
|
|
489
489
|
name: "base",
|
|
490
490
|
custom: {
|
|
491
491
|
morpho: {
|
|
492
|
-
address: "
|
|
493
|
-
blockCreated:
|
|
492
|
+
address: "0x26378861d9c740fe86e7472752aef5b1a783c60b",
|
|
493
|
+
blockCreated: 43606117
|
|
494
494
|
},
|
|
495
495
|
morphoBlue: {
|
|
496
496
|
address: "0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb",
|
|
@@ -519,8 +519,8 @@ const chains$1 = {
|
|
|
519
519
|
name: "ethereum-virtual-testnet",
|
|
520
520
|
custom: {
|
|
521
521
|
morpho: {
|
|
522
|
-
address: "
|
|
523
|
-
blockCreated:
|
|
522
|
+
address: "0x94c576ee728ee290116ee65c0d1e9fed4a1b5041",
|
|
523
|
+
blockCreated: 23244323
|
|
524
524
|
},
|
|
525
525
|
morphoBlue: {
|
|
526
526
|
address: "0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb",
|
|
@@ -941,6 +941,7 @@ const transformAddress = (val, ctx) => {
|
|
|
941
941
|
});
|
|
942
942
|
return z$1.NEVER;
|
|
943
943
|
};
|
|
944
|
+
const AddressSchema = z$1.string().transform(transformAddress);
|
|
944
945
|
|
|
945
946
|
//#endregion
|
|
946
947
|
//#region src/core/LLTV.ts
|
|
@@ -1025,10 +1026,10 @@ const abi$1 = [
|
|
|
1025
1026
|
}
|
|
1026
1027
|
];
|
|
1027
1028
|
const CollateralSchema = z$1.object({
|
|
1028
|
-
asset:
|
|
1029
|
-
oracle:
|
|
1029
|
+
asset: AddressSchema,
|
|
1030
|
+
oracle: AddressSchema,
|
|
1030
1031
|
lltv: LLTVSchema,
|
|
1031
|
-
maxLif: z$1.bigint({ coerce: true }).min(0n)
|
|
1032
|
+
maxLif: z$1.bigint({ coerce: true }).min(0n)
|
|
1032
1033
|
});
|
|
1033
1034
|
const CollateralsSchema = z$1.array(CollateralSchema).min(1, { message: "At least one collateral is required" }).refine((collaterals) => {
|
|
1034
1035
|
for (let i = 1; i < collaterals.length; i++) if (collaterals[i - 1].asset.toLowerCase() > collaterals[i].asset.toLowerCase()) return false;
|
|
@@ -1046,7 +1047,7 @@ const from$16 = (parameters) => {
|
|
|
1046
1047
|
return {
|
|
1047
1048
|
asset: parameters.asset.toLowerCase(),
|
|
1048
1049
|
lltv: from$17(parameters.lltv),
|
|
1049
|
-
maxLif: parameters.maxLif
|
|
1050
|
+
maxLif: parameters.maxLif,
|
|
1050
1051
|
oracle: parameters.oracle.toLowerCase()
|
|
1051
1052
|
};
|
|
1052
1053
|
};
|
|
@@ -1186,14 +1187,8 @@ var Maturity_exports = /* @__PURE__ */ __exportAll({
|
|
|
1186
1187
|
MaturityType: () => MaturityType,
|
|
1187
1188
|
from: () => from$15
|
|
1188
1189
|
});
|
|
1189
|
-
const
|
|
1190
|
-
|
|
1191
|
-
from$15(maturity);
|
|
1192
|
-
return true;
|
|
1193
|
-
} catch (_e) {
|
|
1194
|
-
return false;
|
|
1195
|
-
}
|
|
1196
|
-
}, { error: (issue) => {
|
|
1190
|
+
const MAX_TIMESTAMP_SECONDS = 999999999999;
|
|
1191
|
+
const MaturitySchema = z$1.number().int().max(MAX_TIMESTAMP_SECONDS).refine(isAt15UTC, { error: (issue) => {
|
|
1197
1192
|
try {
|
|
1198
1193
|
return `The maturity is set to ${/* @__PURE__ */ new Date(issue.input * 1e3)}. It must be at 15:00:00 UTC.`;
|
|
1199
1194
|
} catch (_) {
|
|
@@ -1228,7 +1223,7 @@ function from$15(ts) {
|
|
|
1228
1223
|
if (ts in MaturityOptions) return MaturityOptions[ts]();
|
|
1229
1224
|
throw new InvalidOptionError(ts);
|
|
1230
1225
|
}
|
|
1231
|
-
if (typeof ts === "number" && ts >
|
|
1226
|
+
if (typeof ts === "number" && ts > MAX_TIMESTAMP_SECONDS) throw new InvalidFormatError();
|
|
1232
1227
|
if (!isAt15UTC(ts)) throw new InvalidDateError(ts);
|
|
1233
1228
|
return ts;
|
|
1234
1229
|
}
|
|
@@ -1322,7 +1317,7 @@ var Obligation_exports = /* @__PURE__ */ __exportAll({
|
|
|
1322
1317
|
tupleAbi: () => tupleAbi
|
|
1323
1318
|
});
|
|
1324
1319
|
const ObligationSchema = z$1.object({
|
|
1325
|
-
loanToken:
|
|
1320
|
+
loanToken: AddressSchema,
|
|
1326
1321
|
collaterals: CollateralsSchema,
|
|
1327
1322
|
maturity: MaturitySchema,
|
|
1328
1323
|
rcfThreshold: z$1.bigint({ coerce: true }).min(0n)
|
|
@@ -1365,7 +1360,8 @@ const tupleAbi = [{
|
|
|
1365
1360
|
* Collateral.from({
|
|
1366
1361
|
* asset: privateKeyToAccount(generatePrivateKey()).address,
|
|
1367
1362
|
* oracle: privateKeyToAccount(generatePrivateKey()).address,
|
|
1368
|
-
* lltv: 0.965
|
|
1363
|
+
* lltv: 0.965,
|
|
1364
|
+
* maxLif: 0n,
|
|
1369
1365
|
* }),
|
|
1370
1366
|
* ],
|
|
1371
1367
|
* maturity: Maturity.from("end_of_next_quarter"),
|
|
@@ -1424,7 +1420,7 @@ function key(parameters) {
|
|
|
1424
1420
|
parameters.collaterals.map((c) => ({
|
|
1425
1421
|
token: c.asset.toLowerCase(),
|
|
1426
1422
|
lltv: c.lltv,
|
|
1427
|
-
maxLif: c.maxLif
|
|
1423
|
+
maxLif: c.maxLif,
|
|
1428
1424
|
oracle: c.oracle.toLowerCase()
|
|
1429
1425
|
})),
|
|
1430
1426
|
BigInt(parameters.maturity),
|
|
@@ -1497,7 +1493,7 @@ function creationCode(parameters) {
|
|
|
1497
1493
|
collaterals: parameters.obligation.collaterals.map((collateral) => ({
|
|
1498
1494
|
token: collateral.asset.toLowerCase(),
|
|
1499
1495
|
lltv: collateral.lltv,
|
|
1500
|
-
maxLif: collateral.maxLif
|
|
1496
|
+
maxLif: collateral.maxLif,
|
|
1501
1497
|
oracle: collateral.oracle.toLowerCase()
|
|
1502
1498
|
})),
|
|
1503
1499
|
maturity: BigInt(parameters.obligation.maturity),
|
|
@@ -1624,8 +1620,8 @@ let Status = /* @__PURE__ */ function(Status) {
|
|
|
1624
1620
|
}({});
|
|
1625
1621
|
const OfferSchema = () => {
|
|
1626
1622
|
return z$1.object({
|
|
1627
|
-
maker:
|
|
1628
|
-
|
|
1623
|
+
maker: AddressSchema,
|
|
1624
|
+
maxUnits: z$1.bigint({ coerce: true }).min(0n).max(maxUint256).optional().default(0n),
|
|
1629
1625
|
tick: z$1.coerce.number().int().min(0).max(990),
|
|
1630
1626
|
maturity: MaturitySchema,
|
|
1631
1627
|
rcfThreshold: z$1.bigint({ coerce: true }).min(0n).max(maxUint256),
|
|
@@ -1642,13 +1638,13 @@ const OfferSchema = () => {
|
|
|
1642
1638
|
z$1.bigint()
|
|
1643
1639
|
]).optional().default("0x0000000000000000000000000000000000000000000000000000000000000000").transform(transformBytes32),
|
|
1644
1640
|
buy: z$1.boolean(),
|
|
1645
|
-
loanToken:
|
|
1641
|
+
loanToken: AddressSchema,
|
|
1646
1642
|
collaterals: CollateralsSchema,
|
|
1647
1643
|
callback: z$1.object({
|
|
1648
|
-
address:
|
|
1644
|
+
address: AddressSchema,
|
|
1649
1645
|
data: z$1.string().transform(transformHex)
|
|
1650
1646
|
}),
|
|
1651
|
-
receiverIfMakerIsSeller:
|
|
1647
|
+
receiverIfMakerIsSeller: AddressSchema,
|
|
1652
1648
|
exitOnly: z$1.boolean().optional().default(false)
|
|
1653
1649
|
}).refine((data) => data.start < data.expiry, {
|
|
1654
1650
|
message: "start must be before expiry",
|
|
@@ -1701,7 +1697,7 @@ function toSnakeCase(offer) {
|
|
|
1701
1697
|
*/
|
|
1702
1698
|
const serialize = (offer) => ({
|
|
1703
1699
|
maker: offer.maker,
|
|
1704
|
-
|
|
1700
|
+
maxUnits: offer.maxUnits.toString(),
|
|
1705
1701
|
tick: offer.tick,
|
|
1706
1702
|
maturity: Number(offer.maturity),
|
|
1707
1703
|
rcfThreshold: offer.rcfThreshold.toString(),
|
|
@@ -1759,7 +1755,7 @@ function random$1(config) {
|
|
|
1759
1755
|
const loanTokenDecimals = config?.assetsDecimals?.[loanToken] ?? 18;
|
|
1760
1756
|
const unit = BigInt(10) ** BigInt(loanTokenDecimals);
|
|
1761
1757
|
const amountBase = BigInt(100 + int(999901));
|
|
1762
|
-
const
|
|
1758
|
+
const maxUnitsScaled = config?.maxUnits ?? amountBase * unit;
|
|
1763
1759
|
const emptyCallback = {
|
|
1764
1760
|
address: zeroAddress,
|
|
1765
1761
|
data: "0x"
|
|
@@ -1767,7 +1763,7 @@ function random$1(config) {
|
|
|
1767
1763
|
const maker = config?.maker ?? address();
|
|
1768
1764
|
return from$13({
|
|
1769
1765
|
maker,
|
|
1770
|
-
|
|
1766
|
+
maxUnits: maxUnitsScaled,
|
|
1771
1767
|
tick,
|
|
1772
1768
|
maturity,
|
|
1773
1769
|
rcfThreshold: config?.rcfThreshold ?? 0n,
|
|
@@ -1821,7 +1817,7 @@ function hash$1(offer) {
|
|
|
1821
1817
|
* Obligation obligation; // nested tuple
|
|
1822
1818
|
* bool buy;
|
|
1823
1819
|
* address maker;
|
|
1824
|
-
* uint256
|
|
1820
|
+
* uint256 maxUnits;
|
|
1825
1821
|
* uint256 start;
|
|
1826
1822
|
* uint256 expiry;
|
|
1827
1823
|
* uint256 tick;
|
|
@@ -1887,7 +1883,7 @@ const OfferAbi = [{
|
|
|
1887
1883
|
type: "address"
|
|
1888
1884
|
},
|
|
1889
1885
|
{
|
|
1890
|
-
name: "
|
|
1886
|
+
name: "maxUnits",
|
|
1891
1887
|
type: "uint256"
|
|
1892
1888
|
},
|
|
1893
1889
|
{
|
|
@@ -1935,7 +1931,7 @@ function encode$1(offer) {
|
|
|
1935
1931
|
collaterals: offer.collaterals.map((c) => ({
|
|
1936
1932
|
token: c.asset,
|
|
1937
1933
|
lltv: c.lltv,
|
|
1938
|
-
maxLif: c.maxLif
|
|
1934
|
+
maxLif: c.maxLif,
|
|
1939
1935
|
oracle: c.oracle
|
|
1940
1936
|
})),
|
|
1941
1937
|
maturity: BigInt(offer.maturity),
|
|
@@ -1943,7 +1939,7 @@ function encode$1(offer) {
|
|
|
1943
1939
|
},
|
|
1944
1940
|
buy: offer.buy,
|
|
1945
1941
|
maker: offer.maker,
|
|
1946
|
-
|
|
1942
|
+
maxUnits: offer.maxUnits,
|
|
1947
1943
|
start: BigInt(offer.start),
|
|
1948
1944
|
expiry: BigInt(offer.expiry),
|
|
1949
1945
|
tick: BigInt(offer.tick),
|
|
@@ -1977,7 +1973,7 @@ function decode$1(data) {
|
|
|
1977
1973
|
rcfThreshold: s.obligation.rcfThreshold,
|
|
1978
1974
|
buy: s.buy,
|
|
1979
1975
|
maker: s.maker,
|
|
1980
|
-
|
|
1976
|
+
maxUnits: s.maxUnits,
|
|
1981
1977
|
start: Number(s.start),
|
|
1982
1978
|
expiry: Number(s.expiry),
|
|
1983
1979
|
tick: Number(s.tick),
|
|
@@ -2041,7 +2037,7 @@ const takeEvent = {
|
|
|
2041
2037
|
internalType: "uint256"
|
|
2042
2038
|
},
|
|
2043
2039
|
{
|
|
2044
|
-
name: "
|
|
2040
|
+
name: "units",
|
|
2045
2041
|
type: "uint256",
|
|
2046
2042
|
indexed: false,
|
|
2047
2043
|
internalType: "uint256"
|
|
@@ -2127,7 +2123,7 @@ const repayEvent = {
|
|
|
2127
2123
|
internalType: "bytes32"
|
|
2128
2124
|
},
|
|
2129
2125
|
{
|
|
2130
|
-
name: "
|
|
2126
|
+
name: "units",
|
|
2131
2127
|
type: "uint256",
|
|
2132
2128
|
indexed: false,
|
|
2133
2129
|
internalType: "uint256"
|
|
@@ -2444,10 +2440,10 @@ var Tick_exports = /* @__PURE__ */ __exportAll({
|
|
|
2444
2440
|
InvalidTickError: () => InvalidTickError,
|
|
2445
2441
|
MAX_PRICE: () => MAX_PRICE,
|
|
2446
2442
|
TICK_RANGE: () => TICK_RANGE,
|
|
2447
|
-
|
|
2448
|
-
obligationUnitsToAssets: () => obligationUnitsToAssets,
|
|
2443
|
+
assetsToUnits: () => assetsToUnits,
|
|
2449
2444
|
priceToTick: () => priceToTick,
|
|
2450
|
-
tickToPrice: () => tickToPrice
|
|
2445
|
+
tickToPrice: () => tickToPrice,
|
|
2446
|
+
unitsToAssets: () => unitsToAssets
|
|
2451
2447
|
});
|
|
2452
2448
|
/** ln(1 + 0.025), scaled by 1e18. Matches TickLib onchain constant. */
|
|
2453
2449
|
const LN_ONE_PLUS_DELTA = 24692612590371501n;
|
|
@@ -2506,24 +2502,79 @@ function assertPrice(price) {
|
|
|
2506
2502
|
if (price < 0n || price > MAX_PRICE) throw new InvalidPriceError(price);
|
|
2507
2503
|
}
|
|
2508
2504
|
/**
|
|
2509
|
-
* Converts
|
|
2510
|
-
*
|
|
2505
|
+
* Converts units into maker-side assets using the raw tick price surface.
|
|
2506
|
+
* This is the public forward conversion used by the router for lot sizing and other maker-facing capacity math.
|
|
2507
|
+
* - `buy = true` -> `floor(units * price / WAD)`
|
|
2508
|
+
* - `buy = false` -> `ceil(units * price / WAD)`
|
|
2509
|
+
* @param units - The units to convert.
|
|
2511
2510
|
* @param tick - The offer tick.
|
|
2512
|
-
* @
|
|
2511
|
+
* @param buy - Whether the maker side of the offer is buy (`true`) or sell (`false`).
|
|
2512
|
+
* @returns The equivalent amount in maker-side assets.
|
|
2513
2513
|
*/
|
|
2514
|
-
function
|
|
2515
|
-
|
|
2514
|
+
function unitsToAssets(units, tick, buy) {
|
|
2515
|
+
const price = tickToPrice(tick);
|
|
2516
|
+
return buy ? unitsToFloorAssets(units, price) : unitsToCeilAssets(units, price);
|
|
2516
2517
|
}
|
|
2517
2518
|
/**
|
|
2518
|
-
* Converts
|
|
2519
|
-
*
|
|
2519
|
+
* Converts a maker-side asset cap into a safe units cap using the raw tick price.
|
|
2520
|
+
* Buy offers use the max-safe inverse of `floor(units * price / WAD)`.
|
|
2521
|
+
* Sell offers use the max-safe inverse of `ceil(units * price / WAD)`.
|
|
2522
|
+
* The result is clamped to the remaining offer size because the asset cap may have been rounded before inversion.
|
|
2523
|
+
* Zero integer asset caps can still admit positive units on floor-rounded sub-WAD buy ticks, and tick=0 keeps the
|
|
2524
|
+
* whole remaining interval safe because the raw maker-asset surface stays at zero.
|
|
2525
|
+
* @param assets - The integer maker-side asset cap.
|
|
2520
2526
|
* @param tick - The offer tick.
|
|
2521
|
-
* @
|
|
2527
|
+
* @param buy - Whether the maker side of the offer is buy (`true`) or sell (`false`).
|
|
2528
|
+
* @param remainingUnits - The maximum units still available on the offer.
|
|
2529
|
+
* @returns The greatest safe units amount under the maker-side raw-price surface.
|
|
2522
2530
|
*/
|
|
2523
|
-
function
|
|
2531
|
+
function assetsToUnits(assets, tick, buy, remainingUnits) {
|
|
2532
|
+
if (remainingUnits <= 0n) return 0n;
|
|
2533
|
+
if (assets < 0n) return 0n;
|
|
2524
2534
|
const price = tickToPrice(tick);
|
|
2525
|
-
if (price === 0n) return
|
|
2526
|
-
|
|
2535
|
+
if (price === 0n) return remainingUnits;
|
|
2536
|
+
const units = buy ? floorAssetsToUnits(assets, price) : ceilAssetsToUnits(assets, price);
|
|
2537
|
+
return units > remainingUnits ? remainingUnits : units;
|
|
2538
|
+
}
|
|
2539
|
+
/**
|
|
2540
|
+
* Forward conversion for raw-price floor surfaces.
|
|
2541
|
+
* This matches buy-side maker assets and the legacy floor-only helper.
|
|
2542
|
+
* @param units - The units to convert.
|
|
2543
|
+
* @param price - The raw tick price.
|
|
2544
|
+
* @returns The floor-rounded maker-side assets.
|
|
2545
|
+
*/
|
|
2546
|
+
function unitsToFloorAssets(units, price) {
|
|
2547
|
+
return units * price / WAD$1;
|
|
2548
|
+
}
|
|
2549
|
+
/**
|
|
2550
|
+
* Forward conversion for raw-price ceil surfaces.
|
|
2551
|
+
* This matches sell-side maker assets, where the maker receives `sellerAssets` rounded up onchain.
|
|
2552
|
+
* @param units - The units to convert.
|
|
2553
|
+
* @param price - The raw tick price.
|
|
2554
|
+
* @returns The ceil-rounded maker-side assets.
|
|
2555
|
+
*/
|
|
2556
|
+
function unitsToCeilAssets(units, price) {
|
|
2557
|
+
return (units * price + WAD$1 - 1n) / WAD$1;
|
|
2558
|
+
}
|
|
2559
|
+
/**
|
|
2560
|
+
* Max-safe inverse for floor surfaces.
|
|
2561
|
+
* It returns the greatest units value whose floor-rounded maker assets stay within `assets`.
|
|
2562
|
+
* @param assets - The maker-side asset cap.
|
|
2563
|
+
* @param price - The raw tick price.
|
|
2564
|
+
* @returns The greatest safe obligation-units amount under `floor(units * price / WAD) <= assets`.
|
|
2565
|
+
*/
|
|
2566
|
+
function floorAssetsToUnits(assets, price) {
|
|
2567
|
+
return ((assets + 1n) * WAD$1 - 1n) / price;
|
|
2568
|
+
}
|
|
2569
|
+
/**
|
|
2570
|
+
* Max-safe inverse for ceil surfaces.
|
|
2571
|
+
* It returns the greatest units value whose ceil-rounded maker assets stay within `assets`.
|
|
2572
|
+
* @param assets - The maker-side asset cap.
|
|
2573
|
+
* @param price - The raw tick price.
|
|
2574
|
+
* @returns The greatest safe obligation-units amount under `ceil(units * price / WAD) <= assets`.
|
|
2575
|
+
*/
|
|
2576
|
+
function ceilAssetsToUnits(assets, price) {
|
|
2577
|
+
return assets * WAD$1 / price;
|
|
2527
2578
|
}
|
|
2528
2579
|
var InvalidTickError = class extends BaseError {
|
|
2529
2580
|
name = "Tick.InvalidTickError";
|
|
@@ -4069,6 +4120,10 @@ function* ask(operation) {
|
|
|
4069
4120
|
|
|
4070
4121
|
//#endregion
|
|
4071
4122
|
//#region src/indexer/engine/adapter/appliers/applyChainState.ts
|
|
4123
|
+
const emptyOutcome = () => ({
|
|
4124
|
+
stats: [],
|
|
4125
|
+
dbRows: []
|
|
4126
|
+
});
|
|
4072
4127
|
function isChainUninitializedError$1(error) {
|
|
4073
4128
|
return error instanceof Error && error.message.includes("Chain state not initialized");
|
|
4074
4129
|
}
|
|
@@ -4117,7 +4172,7 @@ const chainStateAppliers = {
|
|
|
4117
4172
|
context.chainMutationState.expectedTipHashForWrite = advanceParameters.tipHash;
|
|
4118
4173
|
}
|
|
4119
4174
|
context.chainMutationState.expectedChainState = nextChainState;
|
|
4120
|
-
return
|
|
4175
|
+
return emptyOutcome();
|
|
4121
4176
|
},
|
|
4122
4177
|
collector: async ({ mutation, dbTx, context }) => {
|
|
4123
4178
|
const collectorName = context.toCollectorName(mutation.name);
|
|
@@ -4131,7 +4186,7 @@ const chainStateAppliers = {
|
|
|
4131
4186
|
blockNumber: mutation.cursor,
|
|
4132
4187
|
epoch: BigInt(mutation.epoch)
|
|
4133
4188
|
});
|
|
4134
|
-
return
|
|
4189
|
+
return emptyOutcome();
|
|
4135
4190
|
}
|
|
4136
4191
|
};
|
|
4137
4192
|
|
|
@@ -4144,33 +4199,66 @@ const LOTS_PENDING_LINK_TYPE = "offers_lots_missing_group";
|
|
|
4144
4199
|
|
|
4145
4200
|
//#endregion
|
|
4146
4201
|
//#region src/indexer/engine/adapter/appliers/applyMorphoV2.ts
|
|
4202
|
+
const outcome$3 = (parameters) => ({
|
|
4203
|
+
stats: parameters.stats ?? [],
|
|
4204
|
+
dbRows: parameters.dbRows ?? []
|
|
4205
|
+
});
|
|
4147
4206
|
const morphoV2Appliers = {
|
|
4148
4207
|
transfers_create: async ({ mutation, dbTx }) => {
|
|
4149
|
-
await dbTx.transfers.create(mutation.rows);
|
|
4150
|
-
return
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
|
|
4154
|
-
|
|
4208
|
+
const insertedTransfers = await dbTx.transfers.create(mutation.rows);
|
|
4209
|
+
return outcome$3({
|
|
4210
|
+
stats: mutation.rows.length > 0 ? [{
|
|
4211
|
+
entity: "transfer",
|
|
4212
|
+
operation: "inserted",
|
|
4213
|
+
count: mutation.rows.length
|
|
4214
|
+
}] : [],
|
|
4215
|
+
dbRows: insertedTransfers > 0 ? [{
|
|
4216
|
+
table: "transfers",
|
|
4217
|
+
operation: "inserted",
|
|
4218
|
+
count: insertedTransfers
|
|
4219
|
+
}] : []
|
|
4220
|
+
});
|
|
4155
4221
|
},
|
|
4156
4222
|
consumed_create: async ({ mutation, dbTx }) => {
|
|
4157
|
-
await dbTx.consumed.create(mutation.rows);
|
|
4158
|
-
return
|
|
4159
|
-
|
|
4160
|
-
|
|
4161
|
-
|
|
4162
|
-
|
|
4223
|
+
const inserted = await dbTx.consumed.create(mutation.rows);
|
|
4224
|
+
return outcome$3({
|
|
4225
|
+
stats: mutation.rows.length > 0 ? [{
|
|
4226
|
+
entity: "consumed_event",
|
|
4227
|
+
operation: "inserted",
|
|
4228
|
+
count: mutation.rows.length
|
|
4229
|
+
}] : [],
|
|
4230
|
+
dbRows: [...inserted.groupsInserted > 0 ? [{
|
|
4231
|
+
table: "groups",
|
|
4232
|
+
operation: "inserted",
|
|
4233
|
+
count: inserted.groupsInserted
|
|
4234
|
+
}] : [], ...inserted.consumedEventsInserted > 0 ? [{
|
|
4235
|
+
table: "consumed_events",
|
|
4236
|
+
operation: "inserted",
|
|
4237
|
+
count: inserted.consumedEventsInserted
|
|
4238
|
+
}] : []]
|
|
4239
|
+
});
|
|
4163
4240
|
},
|
|
4164
4241
|
seizures_record: async ({ mutation, dbTx, context }) => {
|
|
4165
|
-
await context.pendingStore.applySeizureFacts({
|
|
4242
|
+
const materialized = await context.pendingStore.applySeizureFacts({
|
|
4166
4243
|
dbTx,
|
|
4167
4244
|
seizureFacts: mutation.rows
|
|
4168
4245
|
});
|
|
4169
|
-
return
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
|
|
4246
|
+
return outcome$3({
|
|
4247
|
+
stats: mutation.rows.length > 0 ? [{
|
|
4248
|
+
entity: "seizure_fact",
|
|
4249
|
+
operation: "inserted",
|
|
4250
|
+
count: mutation.rows.length
|
|
4251
|
+
}] : [],
|
|
4252
|
+
dbRows: [...materialized.positionsUpserted > 0 ? [{
|
|
4253
|
+
table: "positions",
|
|
4254
|
+
operation: "upserted",
|
|
4255
|
+
count: materialized.positionsUpserted
|
|
4256
|
+
}] : [], ...materialized.transfersInserted > 0 ? [{
|
|
4257
|
+
table: "transfers",
|
|
4258
|
+
operation: "inserted",
|
|
4259
|
+
count: materialized.transfersInserted
|
|
4260
|
+
}] : []]
|
|
4261
|
+
});
|
|
4174
4262
|
},
|
|
4175
4263
|
morpho_v2_rewind: async ({ mutation, dbTx, context }) => {
|
|
4176
4264
|
const deletedConsumedEvents = await dbTx.consumed.delete({
|
|
@@ -4194,23 +4282,41 @@ const morphoV2Appliers = {
|
|
|
4194
4282
|
});
|
|
4195
4283
|
const deletedTransfers = deletedDebtTransfers + deletedCollateralTransfers;
|
|
4196
4284
|
const stats = [];
|
|
4197
|
-
|
|
4198
|
-
|
|
4199
|
-
|
|
4200
|
-
|
|
4201
|
-
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4285
|
+
const dbRows = [];
|
|
4286
|
+
if (deletedConsumedEvents > 0) {
|
|
4287
|
+
stats.push({
|
|
4288
|
+
entity: "consumed_event",
|
|
4289
|
+
operation: "deleted",
|
|
4290
|
+
count: deletedConsumedEvents
|
|
4291
|
+
});
|
|
4292
|
+
dbRows.push({
|
|
4293
|
+
table: "consumed_events",
|
|
4294
|
+
operation: "deleted",
|
|
4295
|
+
count: deletedConsumedEvents
|
|
4296
|
+
});
|
|
4297
|
+
}
|
|
4298
|
+
if (deletedTransfers > 0) {
|
|
4299
|
+
stats.push({
|
|
4300
|
+
entity: "transfer",
|
|
4301
|
+
operation: "deleted",
|
|
4302
|
+
count: deletedTransfers
|
|
4303
|
+
});
|
|
4304
|
+
dbRows.push({
|
|
4305
|
+
table: "transfers",
|
|
4306
|
+
operation: "deleted",
|
|
4307
|
+
count: deletedTransfers
|
|
4308
|
+
});
|
|
4309
|
+
}
|
|
4310
|
+
return outcome$3({
|
|
4311
|
+
stats,
|
|
4312
|
+
dbRows
|
|
4206
4313
|
});
|
|
4207
|
-
return stats;
|
|
4208
4314
|
}
|
|
4209
4315
|
};
|
|
4210
4316
|
|
|
4211
4317
|
//#endregion
|
|
4212
4318
|
//#region src/database/drizzle/VERSION.ts
|
|
4213
|
-
const VERSION = "router_v1.
|
|
4319
|
+
const VERSION = "router_v1.16";
|
|
4214
4320
|
|
|
4215
4321
|
//#endregion
|
|
4216
4322
|
//#region src/database/drizzle/schema.ts
|
|
@@ -4358,7 +4464,7 @@ const oracles$1 = s.table(EnumTableName.ORACLES, {
|
|
|
4358
4464
|
const offers = s.table(EnumTableName.OFFERS, {
|
|
4359
4465
|
hash: varchar("hash", { length: 66 }).notNull(),
|
|
4360
4466
|
obligationId: varchar("obligation_id", { length: 66 }).notNull().references(() => obligationIdKeys.obligationId, { onDelete: "cascade" }),
|
|
4361
|
-
|
|
4467
|
+
maxUnits: numeric("max_units", {
|
|
4362
4468
|
precision: 78,
|
|
4363
4469
|
scale: 0
|
|
4364
4470
|
}).notNull().default("0"),
|
|
@@ -4399,8 +4505,8 @@ const offers = s.table(EnumTableName.OFFERS, {
|
|
|
4399
4505
|
index("offers_obligation_side_tick_idx").on(table.obligationId, table.buy, table.tick),
|
|
4400
4506
|
index("offers_obligation_active_tick_idx").on(table.obligationId, table.buy, table.expiry, table.maturity, table.start, table.tick),
|
|
4401
4507
|
index("offers_group_maker_idx").on(table.groupMaker, table.hash, table.obligationId),
|
|
4402
|
-
index("offers_group_winner_expr_idx").on(table.groupChainId, table.groupMaker, table.group, table.obligationId, table.buy, sql`(CASE WHEN "buy" THEN -"tick" ELSE "tick" END)`, table.blockNumber, sql`"
|
|
4403
|
-
index("offers_book_winners_covering_idx").on(table.obligationId, table.buy, table.groupChainId, table.groupMaker, table.group, sql`(CASE WHEN "buy" THEN -"tick" ELSE "tick" END)`, table.blockNumber, sql`"
|
|
4508
|
+
index("offers_group_winner_expr_idx").on(table.groupChainId, table.groupMaker, table.group, table.obligationId, table.buy, sql`(CASE WHEN "buy" THEN -"tick" ELSE "tick" END)`, table.blockNumber, sql`"max_units" DESC`, table.hash),
|
|
4509
|
+
index("offers_book_winners_covering_idx").on(table.obligationId, table.buy, table.groupChainId, table.groupMaker, table.group, sql`(CASE WHEN "buy" THEN -"tick" ELSE "tick" END)`, table.blockNumber, sql`"max_units" DESC`, table.hash)
|
|
4404
4510
|
]);
|
|
4405
4511
|
const offersCallbacks = s.table(EnumTableName.OFFERS_CALLBACKS, {
|
|
4406
4512
|
offerHash: varchar("offer_hash", { length: 66 }).notNull(),
|
|
@@ -4701,7 +4807,12 @@ const buildGroupReferenceKey = (chainId, maker, group) => `${chainId}:${maker.to
|
|
|
4701
4807
|
const buildCallbacksMissingOfferReference = (row) => `${row.offerHash.toLowerCase()}:${row.obligationId.toLowerCase()}`;
|
|
4702
4808
|
const buildMerklePathMissingOfferReference = (row) => `${row.offerHash.toLowerCase()}:${row.obligationId.toLowerCase()}:${row.treeRoot.toLowerCase()}`;
|
|
4703
4809
|
const buildLotMissingGroupReference = (row) => `${row.positionChainId}:${row.positionUser.toLowerCase()}:${row.group.toLowerCase()}:${row.obligationId.toLowerCase()}`;
|
|
4704
|
-
const
|
|
4810
|
+
const entityStat = (parameters) => parameters.count > 0 ? [parameters] : [];
|
|
4811
|
+
const dbRowStat = (parameters) => parameters.count > 0 ? [parameters] : [];
|
|
4812
|
+
const outcome$2 = (parameters) => ({
|
|
4813
|
+
stats: parameters.stats ?? [],
|
|
4814
|
+
dbRows: parameters.dbRows ?? []
|
|
4815
|
+
});
|
|
4705
4816
|
async function selectExistingOfferKeys(parameters) {
|
|
4706
4817
|
const { context, dbTx, references } = parameters;
|
|
4707
4818
|
if (references.length === 0) return /* @__PURE__ */ new Set();
|
|
@@ -4782,45 +4893,93 @@ async function partitionLotsByGroupExistence(parameters) {
|
|
|
4782
4893
|
}
|
|
4783
4894
|
const offersAppliers = {
|
|
4784
4895
|
obligations_create: async ({ mutation, dbTx }) => {
|
|
4785
|
-
await dbTx.obligations.create(mutation.rows);
|
|
4786
|
-
return
|
|
4787
|
-
|
|
4788
|
-
|
|
4789
|
-
|
|
4896
|
+
const inserted = await dbTx.obligations.create(mutation.rows);
|
|
4897
|
+
return outcome$2({
|
|
4898
|
+
stats: entityStat({
|
|
4899
|
+
entity: "obligation",
|
|
4900
|
+
operation: "inserted",
|
|
4901
|
+
count: mutation.rows.length
|
|
4902
|
+
}),
|
|
4903
|
+
dbRows: [
|
|
4904
|
+
...dbRowStat({
|
|
4905
|
+
table: "obligations",
|
|
4906
|
+
operation: "inserted",
|
|
4907
|
+
count: inserted.obligationsInserted
|
|
4908
|
+
}),
|
|
4909
|
+
...dbRowStat({
|
|
4910
|
+
table: "obligation_id_keys",
|
|
4911
|
+
operation: "inserted",
|
|
4912
|
+
count: inserted.obligationIdKeysInserted
|
|
4913
|
+
}),
|
|
4914
|
+
...dbRowStat({
|
|
4915
|
+
table: "obligation_collaterals_v2",
|
|
4916
|
+
operation: "inserted",
|
|
4917
|
+
count: inserted.obligationCollateralsInserted
|
|
4918
|
+
})
|
|
4919
|
+
]
|
|
4790
4920
|
});
|
|
4791
4921
|
},
|
|
4792
4922
|
groups_create: async ({ mutation, dbTx }) => {
|
|
4793
|
-
await dbTx.groups.create(mutation.rows);
|
|
4794
|
-
return
|
|
4795
|
-
|
|
4796
|
-
|
|
4797
|
-
|
|
4923
|
+
const insertedGroups = await dbTx.groups.create(mutation.rows);
|
|
4924
|
+
return outcome$2({
|
|
4925
|
+
stats: entityStat({
|
|
4926
|
+
entity: "group",
|
|
4927
|
+
operation: "inserted",
|
|
4928
|
+
count: mutation.rows.length
|
|
4929
|
+
}),
|
|
4930
|
+
dbRows: dbRowStat({
|
|
4931
|
+
table: "groups",
|
|
4932
|
+
operation: "inserted",
|
|
4933
|
+
count: insertedGroups
|
|
4934
|
+
})
|
|
4798
4935
|
});
|
|
4799
4936
|
},
|
|
4800
4937
|
offers_create: async ({ mutation, dbTx }) => {
|
|
4801
|
-
await dbTx.offers.create(mutation.batches);
|
|
4802
|
-
return
|
|
4803
|
-
|
|
4804
|
-
|
|
4805
|
-
|
|
4938
|
+
const insertedOffers = await dbTx.offers.create(mutation.batches);
|
|
4939
|
+
return outcome$2({
|
|
4940
|
+
stats: entityStat({
|
|
4941
|
+
entity: "offer",
|
|
4942
|
+
operation: "inserted",
|
|
4943
|
+
count: insertedOffers.length
|
|
4944
|
+
}),
|
|
4945
|
+
dbRows: dbRowStat({
|
|
4946
|
+
table: "offers",
|
|
4947
|
+
operation: "inserted",
|
|
4948
|
+
count: insertedOffers.length
|
|
4949
|
+
})
|
|
4806
4950
|
});
|
|
4807
4951
|
},
|
|
4808
4952
|
offers_rewind: async ({ mutation, dbTx, context }) => {
|
|
4809
|
-
|
|
4810
|
-
|
|
4811
|
-
|
|
4812
|
-
|
|
4813
|
-
|
|
4814
|
-
|
|
4953
|
+
const deletedOffers = await dbTx.offers.delete({
|
|
4954
|
+
chainId: context.chainId,
|
|
4955
|
+
blockNumberGte: mutation.blockNumberGte
|
|
4956
|
+
});
|
|
4957
|
+
return outcome$2({
|
|
4958
|
+
stats: entityStat({
|
|
4959
|
+
entity: "offer",
|
|
4960
|
+
operation: "deleted",
|
|
4961
|
+
count: deletedOffers
|
|
4962
|
+
}),
|
|
4963
|
+
dbRows: dbRowStat({
|
|
4964
|
+
table: "offers",
|
|
4965
|
+
operation: "deleted",
|
|
4966
|
+
count: deletedOffers
|
|
4815
4967
|
})
|
|
4816
4968
|
});
|
|
4817
4969
|
},
|
|
4818
4970
|
trees_upsert: async ({ mutation, dbTx }) => {
|
|
4819
|
-
await dbTx.trees.upsert(mutation.rows);
|
|
4820
|
-
return
|
|
4821
|
-
|
|
4822
|
-
|
|
4823
|
-
|
|
4971
|
+
const upsertedRoots = await dbTx.trees.upsert(mutation.rows);
|
|
4972
|
+
return outcome$2({
|
|
4973
|
+
stats: entityStat({
|
|
4974
|
+
entity: "tree",
|
|
4975
|
+
operation: "upserted",
|
|
4976
|
+
count: mutation.rows.length
|
|
4977
|
+
}),
|
|
4978
|
+
dbRows: dbRowStat({
|
|
4979
|
+
table: "trees",
|
|
4980
|
+
operation: "upserted",
|
|
4981
|
+
count: upsertedRoots.length
|
|
4982
|
+
})
|
|
4824
4983
|
});
|
|
4825
4984
|
},
|
|
4826
4985
|
trees_upsert_paths: async ({ mutation, dbTx, context }) => {
|
|
@@ -4841,15 +5000,22 @@ const offersAppliers = {
|
|
|
4841
5000
|
blockNumber: context.pendingLinkReferenceBlockNumber()
|
|
4842
5001
|
}))
|
|
4843
5002
|
});
|
|
4844
|
-
return
|
|
4845
|
-
|
|
4846
|
-
|
|
4847
|
-
|
|
4848
|
-
|
|
4849
|
-
|
|
4850
|
-
|
|
4851
|
-
|
|
4852
|
-
|
|
5003
|
+
return outcome$2({
|
|
5004
|
+
stats: [...entityStat({
|
|
5005
|
+
entity: "tree_path",
|
|
5006
|
+
operation: "upserted",
|
|
5007
|
+
count: resolvableRows.length
|
|
5008
|
+
}), ...entityStat({
|
|
5009
|
+
entity: "tree_path",
|
|
5010
|
+
operation: "ignored",
|
|
5011
|
+
count: missingRows.length
|
|
5012
|
+
})],
|
|
5013
|
+
dbRows: dbRowStat({
|
|
5014
|
+
table: "merkle_paths",
|
|
5015
|
+
operation: "upserted",
|
|
5016
|
+
count: resolvableRows.length
|
|
5017
|
+
})
|
|
5018
|
+
});
|
|
4853
5019
|
},
|
|
4854
5020
|
callbacks_upsert: async ({ mutation, dbTx, context }) => {
|
|
4855
5021
|
const { resolvableRows, missingRows } = await partitionCallbacksByOfferExistence({
|
|
@@ -4857,7 +5023,10 @@ const offersAppliers = {
|
|
|
4857
5023
|
dbTx,
|
|
4858
5024
|
rows: mutation.rows
|
|
4859
5025
|
});
|
|
4860
|
-
|
|
5026
|
+
const inserted = resolvableRows.length > 0 ? await dbTx.callbacks.upsert(resolvableRows) : {
|
|
5027
|
+
callbacksInserted: 0,
|
|
5028
|
+
offersCallbacksInserted: 0
|
|
5029
|
+
};
|
|
4861
5030
|
await context.pendingStore.recordIgnoredLinks({
|
|
4862
5031
|
dbTx,
|
|
4863
5032
|
records: missingRows.map((row) => ({
|
|
@@ -4869,22 +5038,36 @@ const offersAppliers = {
|
|
|
4869
5038
|
blockNumber: context.pendingLinkReferenceBlockNumber()
|
|
4870
5039
|
}))
|
|
4871
5040
|
});
|
|
4872
|
-
return
|
|
4873
|
-
|
|
4874
|
-
|
|
4875
|
-
|
|
4876
|
-
|
|
4877
|
-
|
|
4878
|
-
|
|
4879
|
-
|
|
4880
|
-
|
|
5041
|
+
return outcome$2({
|
|
5042
|
+
stats: [...entityStat({
|
|
5043
|
+
entity: "callback",
|
|
5044
|
+
operation: "upserted",
|
|
5045
|
+
count: resolvableRows.length
|
|
5046
|
+
}), ...entityStat({
|
|
5047
|
+
entity: "callback",
|
|
5048
|
+
operation: "ignored",
|
|
5049
|
+
count: missingRows.length
|
|
5050
|
+
})],
|
|
5051
|
+
dbRows: [...dbRowStat({
|
|
5052
|
+
table: "callbacks",
|
|
5053
|
+
operation: "inserted",
|
|
5054
|
+
count: inserted.callbacksInserted
|
|
5055
|
+
}), ...dbRowStat({
|
|
5056
|
+
table: "offers_callbacks",
|
|
5057
|
+
operation: "inserted",
|
|
5058
|
+
count: inserted.offersCallbacksInserted
|
|
5059
|
+
})]
|
|
5060
|
+
});
|
|
4881
5061
|
},
|
|
4882
5062
|
lots_create: async ({ mutation, dbTx, context }) => {
|
|
4883
5063
|
const { resolvableRows, missingRows } = await partitionLotsByGroupExistence({
|
|
4884
5064
|
dbTx,
|
|
4885
5065
|
rows: mutation.rows
|
|
4886
5066
|
});
|
|
4887
|
-
|
|
5067
|
+
const inserted = resolvableRows.length > 0 ? await dbTx.lots.create(resolvableRows) : {
|
|
5068
|
+
lotsPositionsInserted: 0,
|
|
5069
|
+
lotsInserted: 0
|
|
5070
|
+
};
|
|
4888
5071
|
await context.pendingStore.recordIgnoredLinks({
|
|
4889
5072
|
dbTx,
|
|
4890
5073
|
records: missingRows.map((row) => ({
|
|
@@ -4896,43 +5079,76 @@ const offersAppliers = {
|
|
|
4896
5079
|
blockNumber: context.pendingLinkReferenceBlockNumber()
|
|
4897
5080
|
}))
|
|
4898
5081
|
});
|
|
4899
|
-
return
|
|
4900
|
-
|
|
4901
|
-
|
|
4902
|
-
|
|
4903
|
-
|
|
4904
|
-
|
|
4905
|
-
|
|
4906
|
-
|
|
4907
|
-
|
|
5082
|
+
return outcome$2({
|
|
5083
|
+
stats: [...entityStat({
|
|
5084
|
+
entity: "lot",
|
|
5085
|
+
operation: "inserted",
|
|
5086
|
+
count: resolvableRows.length
|
|
5087
|
+
}), ...entityStat({
|
|
5088
|
+
entity: "lot",
|
|
5089
|
+
operation: "ignored",
|
|
5090
|
+
count: missingRows.length
|
|
5091
|
+
})],
|
|
5092
|
+
dbRows: [...dbRowStat({
|
|
5093
|
+
table: "lots_positions",
|
|
5094
|
+
operation: "inserted",
|
|
5095
|
+
count: inserted.lotsPositionsInserted
|
|
5096
|
+
}), ...dbRowStat({
|
|
5097
|
+
table: "lots",
|
|
5098
|
+
operation: "inserted",
|
|
5099
|
+
count: inserted.lotsInserted
|
|
5100
|
+
})]
|
|
5101
|
+
});
|
|
4908
5102
|
}
|
|
4909
5103
|
};
|
|
4910
5104
|
|
|
4911
5105
|
//#endregion
|
|
4912
5106
|
//#region src/indexer/engine/adapter/appliers/applyOracle.ts
|
|
5107
|
+
const outcome$1 = (parameters) => ({
|
|
5108
|
+
stats: parameters.stats ?? [],
|
|
5109
|
+
dbRows: parameters.dbRows ?? []
|
|
5110
|
+
});
|
|
4913
5111
|
const oracleApplier = { oracle: async ({ mutation, dbTx, context }) => {
|
|
4914
|
-
await dbTx.oracles.upsert(mutation.rows.map((row) => ({
|
|
5112
|
+
const upsertedOracles = await dbTx.oracles.upsert(mutation.rows.map((row) => ({
|
|
4915
5113
|
chainId: context.chainId,
|
|
4916
5114
|
...row,
|
|
4917
5115
|
address: row.address
|
|
4918
5116
|
})));
|
|
4919
|
-
return
|
|
4920
|
-
|
|
4921
|
-
|
|
4922
|
-
|
|
4923
|
-
|
|
5117
|
+
return outcome$1({
|
|
5118
|
+
stats: mutation.rows.length > 0 ? [{
|
|
5119
|
+
entity: "oracle",
|
|
5120
|
+
operation: "upserted",
|
|
5121
|
+
count: mutation.rows.length
|
|
5122
|
+
}] : [],
|
|
5123
|
+
dbRows: upsertedOracles > 0 ? [{
|
|
5124
|
+
table: "oracles",
|
|
5125
|
+
operation: "upserted",
|
|
5126
|
+
count: upsertedOracles
|
|
5127
|
+
}] : []
|
|
5128
|
+
});
|
|
4924
5129
|
} };
|
|
4925
5130
|
|
|
4926
5131
|
//#endregion
|
|
4927
5132
|
//#region src/indexer/engine/adapter/appliers/applyPositions.ts
|
|
5133
|
+
const outcome = (parameters) => ({
|
|
5134
|
+
stats: parameters.stats ?? [],
|
|
5135
|
+
dbRows: parameters.dbRows ?? []
|
|
5136
|
+
});
|
|
4928
5137
|
const positionsAppliers = {
|
|
4929
5138
|
positions_upsert: async ({ mutation, dbTx }) => {
|
|
4930
|
-
await dbTx.positions.upsert(mutation.rows);
|
|
4931
|
-
return
|
|
4932
|
-
|
|
4933
|
-
|
|
4934
|
-
|
|
4935
|
-
|
|
5139
|
+
const upsertedPositions = await dbTx.positions.upsert(mutation.rows);
|
|
5140
|
+
return outcome({
|
|
5141
|
+
stats: mutation.rows.length > 0 ? [{
|
|
5142
|
+
entity: "position",
|
|
5143
|
+
operation: "upserted",
|
|
5144
|
+
count: mutation.rows.length
|
|
5145
|
+
}] : [],
|
|
5146
|
+
dbRows: upsertedPositions > 0 ? [{
|
|
5147
|
+
table: "positions",
|
|
5148
|
+
operation: "upserted",
|
|
5149
|
+
count: upsertedPositions
|
|
5150
|
+
}] : []
|
|
5151
|
+
});
|
|
4936
5152
|
},
|
|
4937
5153
|
positions_rewind: async ({ mutation, dbTx, context }) => {
|
|
4938
5154
|
const deletedPositions = await dbTx.positions.setEmptyAfter({
|
|
@@ -4940,11 +5156,11 @@ const positionsAppliers = {
|
|
|
4940
5156
|
blockNumber: mutation.blockNumberGte,
|
|
4941
5157
|
type: Type.ERC20
|
|
4942
5158
|
});
|
|
4943
|
-
return deletedPositions > 0 ? [{
|
|
5159
|
+
return outcome({ stats: deletedPositions > 0 ? [{
|
|
4944
5160
|
entity: "position",
|
|
4945
5161
|
operation: "deleted",
|
|
4946
5162
|
count: deletedPositions
|
|
4947
|
-
}] : [];
|
|
5163
|
+
}] : [] });
|
|
4948
5164
|
}
|
|
4949
5165
|
};
|
|
4950
5166
|
|
|
@@ -5257,7 +5473,9 @@ async function materializeSeizureFacts(parameters) {
|
|
|
5257
5473
|
if (seizureFacts.length === 0) return {
|
|
5258
5474
|
unresolvedFacts: [],
|
|
5259
5475
|
transfersCreate: [],
|
|
5260
|
-
positionsUpsert: []
|
|
5476
|
+
positionsUpsert: [],
|
|
5477
|
+
transfersInserted: 0,
|
|
5478
|
+
positionsUpserted: 0
|
|
5261
5479
|
};
|
|
5262
5480
|
const resolutionMap = await resolveCollateralAssetRefs({
|
|
5263
5481
|
dbTx,
|
|
@@ -5285,9 +5503,11 @@ async function materializeSeizureFacts(parameters) {
|
|
|
5285
5503
|
}));
|
|
5286
5504
|
}
|
|
5287
5505
|
const positionsUpsert = toCollateralPositionRows(resolvedTransfers);
|
|
5506
|
+
let positionsUpserted = 0;
|
|
5507
|
+
let transfersInserted = 0;
|
|
5288
5508
|
if (resolvedTransfers.length > 0) {
|
|
5289
|
-
await dbTx.positions.upsert(positionsUpsert);
|
|
5290
|
-
await dbTx.transfers.create(resolvedTransfers);
|
|
5509
|
+
positionsUpserted = await dbTx.positions.upsert(positionsUpsert);
|
|
5510
|
+
transfersInserted = await dbTx.transfers.create(resolvedTransfers);
|
|
5291
5511
|
await recomputeBackfilledCollateralBalances({
|
|
5292
5512
|
dbTx,
|
|
5293
5513
|
transfers: resolvedTransfers
|
|
@@ -5296,7 +5516,9 @@ async function materializeSeizureFacts(parameters) {
|
|
|
5296
5516
|
return {
|
|
5297
5517
|
unresolvedFacts,
|
|
5298
5518
|
transfersCreate: resolvedTransfers,
|
|
5299
|
-
positionsUpsert
|
|
5519
|
+
positionsUpsert,
|
|
5520
|
+
transfersInserted,
|
|
5521
|
+
positionsUpserted
|
|
5300
5522
|
};
|
|
5301
5523
|
}
|
|
5302
5524
|
const toFactsFromPendingRows = (chainId, rows) => rows.map((row) => ({
|
|
@@ -5546,15 +5768,20 @@ const createPendingLinkStore = (parameters) => {
|
|
|
5546
5768
|
const resolverTypes = resolverEntries.map((resolver) => resolver.type);
|
|
5547
5769
|
return {
|
|
5548
5770
|
applySeizureFacts: async ({ dbTx, seizureFacts }) => {
|
|
5771
|
+
const materialized = await materializeSeizureFacts({
|
|
5772
|
+
dbTx,
|
|
5773
|
+
chainId,
|
|
5774
|
+
seizureFacts
|
|
5775
|
+
});
|
|
5549
5776
|
await recordUnresolvedSeizures({
|
|
5550
5777
|
dbTx,
|
|
5551
5778
|
chainId,
|
|
5552
|
-
seizureFacts:
|
|
5553
|
-
dbTx,
|
|
5554
|
-
chainId,
|
|
5555
|
-
seizureFacts
|
|
5556
|
-
})).unresolvedFacts
|
|
5779
|
+
seizureFacts: materialized.unresolvedFacts
|
|
5557
5780
|
});
|
|
5781
|
+
return {
|
|
5782
|
+
positionsUpserted: materialized.positionsUpserted,
|
|
5783
|
+
transfersInserted: materialized.transfersInserted
|
|
5784
|
+
};
|
|
5558
5785
|
},
|
|
5559
5786
|
recordIgnoredLinks: async ({ dbTx, records }) => {
|
|
5560
5787
|
if (records.length === 0) return;
|
|
@@ -5903,6 +6130,7 @@ const create$29 = (parameters) => {
|
|
|
5903
6130
|
chainMutationState
|
|
5904
6131
|
};
|
|
5905
6132
|
const commitAppliedStats = [];
|
|
6133
|
+
const commitAppliedDbRows = [];
|
|
5906
6134
|
const collectorsInCommit = /* @__PURE__ */ new Set();
|
|
5907
6135
|
const dispatchMutation = async (parameters) => {
|
|
5908
6136
|
const applier = mutationAppliers[parameters.mutation.t];
|
|
@@ -5915,18 +6143,24 @@ const create$29 = (parameters) => {
|
|
|
5915
6143
|
try {
|
|
5916
6144
|
await db.transaction(async (dbTx) => {
|
|
5917
6145
|
for (const mutation of tx.muts) {
|
|
5918
|
-
const
|
|
6146
|
+
const mutationApplyOutcome = await dispatchMutation({
|
|
5919
6147
|
mutation,
|
|
5920
6148
|
dbTx
|
|
5921
6149
|
});
|
|
5922
6150
|
if (mutation.collector === void 0) continue;
|
|
5923
6151
|
collectorsInCommit.add(mutation.collector);
|
|
5924
|
-
for (const stat of
|
|
6152
|
+
for (const stat of mutationApplyOutcome.stats) commitAppliedStats.push({
|
|
5925
6153
|
collector: mutation.collector,
|
|
5926
6154
|
entity: stat.entity,
|
|
5927
6155
|
operation: stat.operation,
|
|
5928
6156
|
count: stat.count
|
|
5929
6157
|
});
|
|
6158
|
+
for (const dbRow of mutationApplyOutcome.dbRows) commitAppliedDbRows.push({
|
|
6159
|
+
collector: mutation.collector,
|
|
6160
|
+
table: dbRow.table,
|
|
6161
|
+
operation: dbRow.operation,
|
|
6162
|
+
count: dbRow.count
|
|
6163
|
+
});
|
|
5930
6164
|
}
|
|
5931
6165
|
});
|
|
5932
6166
|
} catch (error) {
|
|
@@ -5941,6 +6175,7 @@ const create$29 = (parameters) => {
|
|
|
5941
6175
|
chainId,
|
|
5942
6176
|
collectors: [...collectorsInCommit],
|
|
5943
6177
|
stats: commitAppliedStats,
|
|
6178
|
+
dbRows: commitAppliedDbRows,
|
|
5944
6179
|
onCommitApplied
|
|
5945
6180
|
});
|
|
5946
6181
|
const nowBlock = state.chain.checkpoints[state.chain.checkpoints.length - 1]?.n ?? 0;
|
|
@@ -5988,19 +6223,21 @@ const create$29 = (parameters) => {
|
|
|
5988
6223
|
function emitCommitAppliedObservation(parameters) {
|
|
5989
6224
|
if (parameters.collectors.length === 0) return;
|
|
5990
6225
|
const aggregatedStats = aggregateCommitAppliedStats(parameters.stats);
|
|
6226
|
+
const aggregatedDbRows = aggregateCommitAppliedDbRows(parameters.dbRows);
|
|
5991
6227
|
try {
|
|
5992
6228
|
parameters.onCommitApplied({
|
|
5993
6229
|
chainId: parameters.chainId,
|
|
5994
6230
|
collectors: parameters.collectors,
|
|
5995
6231
|
committedAtUnixMs: Date.now(),
|
|
5996
|
-
stats: aggregatedStats
|
|
6232
|
+
stats: aggregatedStats,
|
|
6233
|
+
dbRows: aggregatedDbRows
|
|
5997
6234
|
});
|
|
5998
6235
|
} catch {}
|
|
5999
6236
|
}
|
|
6000
6237
|
function aggregateCommitAppliedStats(stats) {
|
|
6001
6238
|
const aggregatedByKey = /* @__PURE__ */ new Map();
|
|
6002
6239
|
for (const stat of stats) {
|
|
6003
|
-
const count =
|
|
6240
|
+
const count = normalizePositiveCount(stat.count);
|
|
6004
6241
|
if (count === null) continue;
|
|
6005
6242
|
const key = `${stat.collector}\u0000${stat.entity}\u0000${stat.operation}`;
|
|
6006
6243
|
const previous = aggregatedByKey.get(key);
|
|
@@ -6021,7 +6258,31 @@ function aggregateCommitAppliedStats(stats) {
|
|
|
6021
6258
|
return left.operation.localeCompare(right.operation);
|
|
6022
6259
|
});
|
|
6023
6260
|
}
|
|
6024
|
-
function
|
|
6261
|
+
function aggregateCommitAppliedDbRows(dbRows) {
|
|
6262
|
+
const aggregatedByKey = /* @__PURE__ */ new Map();
|
|
6263
|
+
for (const dbRow of dbRows) {
|
|
6264
|
+
const count = normalizePositiveCount(dbRow.count);
|
|
6265
|
+
if (count === null) continue;
|
|
6266
|
+
const key = `${dbRow.collector}\u0000${dbRow.table}\u0000${dbRow.operation}`;
|
|
6267
|
+
const previous = aggregatedByKey.get(key);
|
|
6268
|
+
if (previous === void 0) {
|
|
6269
|
+
aggregatedByKey.set(key, {
|
|
6270
|
+
collector: dbRow.collector,
|
|
6271
|
+
table: dbRow.table,
|
|
6272
|
+
operation: dbRow.operation,
|
|
6273
|
+
count
|
|
6274
|
+
});
|
|
6275
|
+
continue;
|
|
6276
|
+
}
|
|
6277
|
+
previous.count += count;
|
|
6278
|
+
}
|
|
6279
|
+
return [...aggregatedByKey.values()].sort((left, right) => {
|
|
6280
|
+
if (left.collector !== right.collector) return left.collector.localeCompare(right.collector);
|
|
6281
|
+
if (left.table !== right.table) return left.table.localeCompare(right.table);
|
|
6282
|
+
return left.operation.localeCompare(right.operation);
|
|
6283
|
+
});
|
|
6284
|
+
}
|
|
6285
|
+
function normalizePositiveCount(value) {
|
|
6025
6286
|
if (!Number.isFinite(value)) return null;
|
|
6026
6287
|
const normalized = Math.trunc(value);
|
|
6027
6288
|
return normalized > 0 ? normalized : null;
|
|
@@ -6251,7 +6512,7 @@ function processConsumedLogs(parameters) {
|
|
|
6251
6512
|
* A debt is modeled as a negative position: borrowing = transfer FROM user TO zeroAddress,
|
|
6252
6513
|
* repayment = FROM zeroAddress TO user. The contract field is the obligationId.
|
|
6253
6514
|
*
|
|
6254
|
-
* **Take event** — Every take is bilateral when
|
|
6515
|
+
* **Take event** — Every take is bilateral when units > 0:
|
|
6255
6516
|
* - Buyer (maker if offerIsBuy, taker otherwise): debt decreases (repaid) → from: 0x0 → to: buyer
|
|
6256
6517
|
* - Seller (taker if offerIsBuy, maker otherwise): debt increases (borrows) → from: seller → to: 0x0
|
|
6257
6518
|
*
|
|
@@ -6283,14 +6544,14 @@ function processDebtTransfers(parameters) {
|
|
|
6283
6544
|
if (eventName === takeEvent.name) {
|
|
6284
6545
|
const args = rawLog.args;
|
|
6285
6546
|
const obligationId = args?.id_;
|
|
6286
|
-
if (obligationId === void 0 || args?.maker === void 0 || args?.taker === void 0 || args?.offerIsBuy === void 0 || args?.
|
|
6547
|
+
if (obligationId === void 0 || args?.maker === void 0 || args?.taker === void 0 || args?.offerIsBuy === void 0 || args?.units === void 0) {
|
|
6287
6548
|
logger.debug({
|
|
6288
6549
|
event: INDEXER_COLLECTOR_LOG_SKIPPED,
|
|
6289
6550
|
msg: "Skipping Take log because it is missing required args for debt"
|
|
6290
6551
|
});
|
|
6291
6552
|
continue;
|
|
6292
6553
|
}
|
|
6293
|
-
if (args.
|
|
6554
|
+
if (args.units === 0n) continue;
|
|
6294
6555
|
const buyer = args.offerIsBuy ? args.maker : args.taker;
|
|
6295
6556
|
const seller = args.offerIsBuy ? args.taker : args.maker;
|
|
6296
6557
|
const blockNumber = Number(rawLog.blockNumber);
|
|
@@ -6300,7 +6561,7 @@ function processDebtTransfers(parameters) {
|
|
|
6300
6561
|
contract: obligationId,
|
|
6301
6562
|
from: zeroAddress,
|
|
6302
6563
|
to: buyer,
|
|
6303
|
-
value: args.
|
|
6564
|
+
value: args.units,
|
|
6304
6565
|
type: Type.DEBT_OF,
|
|
6305
6566
|
asset: zeroAddress,
|
|
6306
6567
|
blockNumber
|
|
@@ -6311,7 +6572,7 @@ function processDebtTransfers(parameters) {
|
|
|
6311
6572
|
contract: obligationId,
|
|
6312
6573
|
from: seller,
|
|
6313
6574
|
to: zeroAddress,
|
|
6314
|
-
value: args.
|
|
6575
|
+
value: args.units,
|
|
6315
6576
|
type: Type.DEBT_OF,
|
|
6316
6577
|
asset: zeroAddress,
|
|
6317
6578
|
blockNumber
|
|
@@ -6321,21 +6582,21 @@ function processDebtTransfers(parameters) {
|
|
|
6321
6582
|
if (eventName === repayEvent.name) {
|
|
6322
6583
|
const args = rawLog.args;
|
|
6323
6584
|
const obligationId = args?.id_;
|
|
6324
|
-
if (obligationId === void 0 || args?.
|
|
6585
|
+
if (obligationId === void 0 || args?.units === void 0 || args?.onBehalf === void 0) {
|
|
6325
6586
|
logger.debug({
|
|
6326
6587
|
event: INDEXER_COLLECTOR_LOG_SKIPPED,
|
|
6327
6588
|
msg: "Skipping Repay log because it is missing required args"
|
|
6328
6589
|
});
|
|
6329
6590
|
continue;
|
|
6330
6591
|
}
|
|
6331
|
-
if (args.
|
|
6592
|
+
if (args.units === 0n) continue;
|
|
6332
6593
|
transfers.push(from$8({
|
|
6333
6594
|
id: `${baseId}-debt-repay`,
|
|
6334
6595
|
chainId,
|
|
6335
6596
|
contract: obligationId,
|
|
6336
6597
|
from: zeroAddress,
|
|
6337
6598
|
to: args.onBehalf,
|
|
6338
|
-
value: args.
|
|
6599
|
+
value: args.units,
|
|
6339
6600
|
type: Type.DEBT_OF,
|
|
6340
6601
|
asset: zeroAddress,
|
|
6341
6602
|
blockNumber: Number(rawLog.blockNumber)
|
|
@@ -6659,6 +6920,15 @@ const processBatchesUntilCursorAdvance = async (stream, cursor, processBatch, op
|
|
|
6659
6920
|
const collectorName$7 = "morpho_v2";
|
|
6660
6921
|
const RESOLVE_CONSUMED_YIELD_EVERY_ITEMS = 256;
|
|
6661
6922
|
const RESOLVE_CONSUMED_YIELD_EVERY_MS = 8;
|
|
6923
|
+
const MORPHO_DERIVED_LOG_ID_SUFFIXES = [
|
|
6924
|
+
"-debt-buyer",
|
|
6925
|
+
"-debt-seller",
|
|
6926
|
+
"-debt-repay",
|
|
6927
|
+
"-debt-liquidate",
|
|
6928
|
+
"-collateral-supply",
|
|
6929
|
+
"-collateral-withdraw",
|
|
6930
|
+
"-collateral-liquidate"
|
|
6931
|
+
];
|
|
6662
6932
|
const runNativeStep$2 = async (parameters) => {
|
|
6663
6933
|
const { request, client, db, logger } = parameters;
|
|
6664
6934
|
const consumedEvents = [];
|
|
@@ -6666,7 +6936,6 @@ const runNativeStep$2 = async (parameters) => {
|
|
|
6666
6936
|
const collateralTransfers = [];
|
|
6667
6937
|
const seizureFacts = [];
|
|
6668
6938
|
let logsIngestedCount = 0;
|
|
6669
|
-
let logsIndexedCount = 0;
|
|
6670
6939
|
const streamStep = await processBatchesUntilCursorAdvance(streamLogs({
|
|
6671
6940
|
client,
|
|
6672
6941
|
contractAddress: client.chain.custom.morpho.address,
|
|
@@ -6691,7 +6960,13 @@ const runNativeStep$2 = async (parameters) => {
|
|
|
6691
6960
|
logs,
|
|
6692
6961
|
strict: false
|
|
6693
6962
|
});
|
|
6694
|
-
|
|
6963
|
+
const untrackedLogsCount = logs.length - parsedLogs.length;
|
|
6964
|
+
if (untrackedLogsCount > 0) logger.debug({
|
|
6965
|
+
event: INDEXER_COLLECTOR_LOG_SKIPPED,
|
|
6966
|
+
msg: "Skipping logs because they do not match tracked Morpho V2 events",
|
|
6967
|
+
reason: "untracked_event",
|
|
6968
|
+
count: untrackedLogsCount
|
|
6969
|
+
});
|
|
6695
6970
|
consumedEvents.push(...processConsumedLogs({
|
|
6696
6971
|
logs: parsedLogs,
|
|
6697
6972
|
chainId: client.chain.id
|
|
@@ -6720,14 +6995,21 @@ const runNativeStep$2 = async (parameters) => {
|
|
|
6720
6995
|
logsIndexedCount: 0
|
|
6721
6996
|
};
|
|
6722
6997
|
const { nextCursor } = streamStep;
|
|
6998
|
+
const resolvedConsumedEvents = await resolveConsumedEvents({
|
|
6999
|
+
db,
|
|
7000
|
+
consumedEvents,
|
|
7001
|
+
logger
|
|
7002
|
+
});
|
|
7003
|
+
const logsIndexedCount = countIndexedMorphoLogs({
|
|
7004
|
+
consumedEvents: resolvedConsumedEvents,
|
|
7005
|
+
debtTransfers,
|
|
7006
|
+
collateralTransfers,
|
|
7007
|
+
seizureFacts
|
|
7008
|
+
});
|
|
6723
7009
|
const domainMutations = buildDomainMutations$1({
|
|
6724
7010
|
debtTransfers,
|
|
6725
7011
|
collateralTransfers,
|
|
6726
|
-
consumedEvents:
|
|
6727
|
-
db,
|
|
6728
|
-
consumedEvents,
|
|
6729
|
-
logger
|
|
6730
|
-
}),
|
|
7012
|
+
consumedEvents: resolvedConsumedEvents,
|
|
6731
7013
|
seizureFacts
|
|
6732
7014
|
});
|
|
6733
7015
|
return {
|
|
@@ -6763,6 +7045,18 @@ const create$28 = (parameters) => {
|
|
|
6763
7045
|
});
|
|
6764
7046
|
};
|
|
6765
7047
|
};
|
|
7048
|
+
function countIndexedMorphoLogs(parameters) {
|
|
7049
|
+
const indexedLogIds = /* @__PURE__ */ new Set();
|
|
7050
|
+
for (const consumedEvent of parameters.consumedEvents) indexedLogIds.add(consumedEvent.id);
|
|
7051
|
+
for (const transfer of parameters.debtTransfers) indexedLogIds.add(stripMorphoDerivedLogIdSuffix(transfer.id));
|
|
7052
|
+
for (const transfer of parameters.collateralTransfers) indexedLogIds.add(stripMorphoDerivedLogIdSuffix(transfer.id));
|
|
7053
|
+
for (const seizureFact of parameters.seizureFacts) indexedLogIds.add(stripMorphoDerivedLogIdSuffix(seizureFact.id));
|
|
7054
|
+
return indexedLogIds.size;
|
|
7055
|
+
}
|
|
7056
|
+
function stripMorphoDerivedLogIdSuffix(id) {
|
|
7057
|
+
for (const suffix of MORPHO_DERIVED_LOG_ID_SUFFIXES) if (id.endsWith(suffix)) return id.slice(0, -suffix.length);
|
|
7058
|
+
return id;
|
|
7059
|
+
}
|
|
6766
7060
|
async function resolveConsumedEvents(parameters) {
|
|
6767
7061
|
const { db, consumedEvents, logger } = parameters;
|
|
6768
7062
|
if (consumedEvents.length === 0) return [];
|
|
@@ -7018,7 +7312,7 @@ const decodeCallbacks = (parameters) => {
|
|
|
7018
7312
|
if (!isEmptyCallback(offer)) continue;
|
|
7019
7313
|
if (offer.buy) {
|
|
7020
7314
|
const loanToken = offer.loanToken.toLowerCase();
|
|
7021
|
-
const positionTypeId$
|
|
7315
|
+
const positionTypeId$3 = positionTypeId(Type.ERC20);
|
|
7022
7316
|
positions.push(from$11({
|
|
7023
7317
|
chainId,
|
|
7024
7318
|
contract: loanToken,
|
|
@@ -7031,10 +7325,10 @@ const decodeCallbacks = (parameters) => {
|
|
|
7031
7325
|
positionChainId: chainId,
|
|
7032
7326
|
positionContract: loanToken,
|
|
7033
7327
|
positionUser: offer.maker,
|
|
7034
|
-
positionTypeId: positionTypeId$
|
|
7328
|
+
positionTypeId: positionTypeId$3,
|
|
7035
7329
|
group: offer.group,
|
|
7036
7330
|
obligationId,
|
|
7037
|
-
size:
|
|
7331
|
+
size: unitsToAssets(offer.maxUnits, offer.tick, offer.buy)
|
|
7038
7332
|
});
|
|
7039
7333
|
callbacks.push({
|
|
7040
7334
|
offerHash: hash$1(offer),
|
|
@@ -7043,22 +7337,22 @@ const decodeCallbacks = (parameters) => {
|
|
|
7043
7337
|
chainId,
|
|
7044
7338
|
contract: loanToken,
|
|
7045
7339
|
user: offer.maker,
|
|
7046
|
-
positionTypeId: positionTypeId$
|
|
7340
|
+
positionTypeId: positionTypeId$3,
|
|
7047
7341
|
type: CallbackType.Empty
|
|
7048
7342
|
}]
|
|
7049
7343
|
});
|
|
7050
7344
|
continue;
|
|
7051
7345
|
}
|
|
7052
7346
|
const contract = obligationId;
|
|
7053
|
-
const positionTypeId$
|
|
7347
|
+
const positionTypeId$2 = positionTypeId(Type.COLLATERAL_OF);
|
|
7054
7348
|
lots.push({
|
|
7055
7349
|
positionChainId: chainId,
|
|
7056
7350
|
positionContract: contract,
|
|
7057
7351
|
positionUser: offer.maker,
|
|
7058
|
-
positionTypeId: positionTypeId$
|
|
7352
|
+
positionTypeId: positionTypeId$2,
|
|
7059
7353
|
group: offer.group,
|
|
7060
7354
|
obligationId,
|
|
7061
|
-
size:
|
|
7355
|
+
size: unitsToAssets(offer.maxUnits, offer.tick, offer.buy)
|
|
7062
7356
|
});
|
|
7063
7357
|
callbacks.push({
|
|
7064
7358
|
offerHash: hash$1(offer),
|
|
@@ -7067,7 +7361,7 @@ const decodeCallbacks = (parameters) => {
|
|
|
7067
7361
|
chainId,
|
|
7068
7362
|
contract,
|
|
7069
7363
|
user: offer.maker,
|
|
7070
|
-
positionTypeId: positionTypeId$
|
|
7364
|
+
positionTypeId: positionTypeId$2,
|
|
7071
7365
|
type: CallbackType.Empty
|
|
7072
7366
|
}]
|
|
7073
7367
|
});
|
|
@@ -7707,9 +8001,11 @@ const runNativeStep = async (parameters) => {
|
|
|
7707
8001
|
});
|
|
7708
8002
|
transfers.push(...stepTransfers.transfers);
|
|
7709
8003
|
logsIndexedCount += stepTransfers.transfers.length;
|
|
7710
|
-
|
|
8004
|
+
if (stepTransfers.skippedInvalidLogs > 0) logger.debug({
|
|
7711
8005
|
event: INDEXER_COLLECTOR_LOG_SKIPPED,
|
|
7712
|
-
msg: "Skipping
|
|
8006
|
+
msg: "Skipping transfer logs because they are missing required fields",
|
|
8007
|
+
reason: "missing_required_fields",
|
|
8008
|
+
count: stepTransfers.skippedInvalidLogs
|
|
7713
8009
|
});
|
|
7714
8010
|
if (shouldContinueStream({
|
|
7715
8011
|
pendingPositionsCount: pendingNewPositions.length,
|
|
@@ -9112,7 +9408,7 @@ const init$1 = (parameters) => {
|
|
|
9112
9408
|
maker: item.offer.maker,
|
|
9113
9409
|
group: item.offer.group,
|
|
9114
9410
|
tick: item.offer.tick,
|
|
9115
|
-
|
|
9411
|
+
max_units: item.offer.maxUnits.toString(),
|
|
9116
9412
|
buy: item.offer.buy
|
|
9117
9413
|
});
|
|
9118
9414
|
}
|
|
@@ -9624,7 +9920,7 @@ function create$19(parameters) {
|
|
|
9624
9920
|
});
|
|
9625
9921
|
}
|
|
9626
9922
|
},
|
|
9627
|
-
onCommitApplied: ({ collectors, stats, committedAtUnixMs }) => {
|
|
9923
|
+
onCommitApplied: ({ collectors, stats, dbRows, committedAtUnixMs }) => {
|
|
9628
9924
|
if (sinks.length === 0) return;
|
|
9629
9925
|
try {
|
|
9630
9926
|
emitObservation(sinks, {
|
|
@@ -9632,6 +9928,7 @@ function create$19(parameters) {
|
|
|
9632
9928
|
chainId,
|
|
9633
9929
|
collectors,
|
|
9634
9930
|
stats,
|
|
9931
|
+
dbRows,
|
|
9635
9932
|
committedAtUnixMs
|
|
9636
9933
|
});
|
|
9637
9934
|
} catch (error) {
|
|
@@ -9687,12 +9984,14 @@ function createObservedLogger(parameters) {
|
|
|
9687
9984
|
const wrap = (level, emit) => {
|
|
9688
9985
|
const enabled = isLogFnEnabled(emit);
|
|
9689
9986
|
return (entry) => {
|
|
9690
|
-
if (
|
|
9987
|
+
if (isIndexerComponent(entry.component) && (enabled || isStructuredCollectorDropLog(entry))) try {
|
|
9691
9988
|
const chainId = parseChainId(entry.chain_id);
|
|
9692
9989
|
if (chainId !== null) parameters.onLogEntry({
|
|
9693
9990
|
type: "runtime.log",
|
|
9694
9991
|
chainId,
|
|
9695
|
-
level
|
|
9992
|
+
level,
|
|
9993
|
+
...extractRuntimeLogMetadata(entry),
|
|
9994
|
+
...enabled ? {} : { emitted: false }
|
|
9696
9995
|
});
|
|
9697
9996
|
} catch {}
|
|
9698
9997
|
emit(entry);
|
|
@@ -9707,6 +10006,18 @@ function createObservedLogger(parameters) {
|
|
|
9707
10006
|
fatal: wrap("fatal", parameters.logger.fatal)
|
|
9708
10007
|
};
|
|
9709
10008
|
}
|
|
10009
|
+
function extractRuntimeLogMetadata(entry) {
|
|
10010
|
+
const event = typeof entry.event === "string" ? entry.event : void 0;
|
|
10011
|
+
const fields = Object.fromEntries(Object.entries(entry).filter(([key]) => key !== "msg" && key !== "component" && key !== "chain_id" && key !== "event"));
|
|
10012
|
+
return {
|
|
10013
|
+
...event === void 0 ? {} : { event },
|
|
10014
|
+
...Object.keys(fields).length === 0 ? {} : { fields }
|
|
10015
|
+
};
|
|
10016
|
+
}
|
|
10017
|
+
function isStructuredCollectorDropLog(entry) {
|
|
10018
|
+
if (entry.event !== INDEXER_COLLECTOR_OFFER_TREE_DECODE_FAILED && entry.event !== INDEXER_COLLECTOR_OFFER_TREE_REJECTED && entry.event !== INDEXER_COLLECTOR_LOG_SKIPPED) return false;
|
|
10019
|
+
return typeof entry.collector === "string" && typeof entry.reason === "string";
|
|
10020
|
+
}
|
|
9710
10021
|
function emitObservation(sinks, observation) {
|
|
9711
10022
|
for (const sink of sinks) sink.observe(observation);
|
|
9712
10023
|
}
|
|
@@ -10349,7 +10660,7 @@ function from$5(level) {
|
|
|
10349
10660
|
return {
|
|
10350
10661
|
tick: level.tick,
|
|
10351
10662
|
price: price.toString(),
|
|
10352
|
-
|
|
10663
|
+
max_units: level.maxUnits.toString(),
|
|
10353
10664
|
count: level.count
|
|
10354
10665
|
};
|
|
10355
10666
|
}
|
|
@@ -10460,7 +10771,7 @@ function from$3(input) {
|
|
|
10460
10771
|
},
|
|
10461
10772
|
buy: input.buy,
|
|
10462
10773
|
maker: input.maker,
|
|
10463
|
-
|
|
10774
|
+
max_units: input.maxUnits.toString(),
|
|
10464
10775
|
start: input.start,
|
|
10465
10776
|
expiry: input.expiry,
|
|
10466
10777
|
tick: input.tick,
|
|
@@ -10619,7 +10930,7 @@ const offerExample = {
|
|
|
10619
10930
|
},
|
|
10620
10931
|
buy: false,
|
|
10621
10932
|
maker: "0x7b093658BE7f90B63D7c359e8f408e503c2D9401",
|
|
10622
|
-
|
|
10933
|
+
max_units: "369216000000000000000000",
|
|
10623
10934
|
start: 1761922790,
|
|
10624
10935
|
expiry: 1761922799,
|
|
10625
10936
|
tick: 495,
|
|
@@ -10662,7 +10973,7 @@ const missingCollectorExample = {
|
|
|
10662
10973
|
};
|
|
10663
10974
|
const validateOfferExample = {
|
|
10664
10975
|
maker: "0x7b093658BE7f90B63D7c359e8f408e503c2D9401",
|
|
10665
|
-
|
|
10976
|
+
max_units: "369216000000000000000000",
|
|
10666
10977
|
tick: 495,
|
|
10667
10978
|
maturity: 1761922799,
|
|
10668
10979
|
rcf_threshold: "0",
|
|
@@ -10816,8 +11127,8 @@ __decorate([ApiProperty({
|
|
|
10816
11127
|
})], OfferDataResponse.prototype, "maker", void 0);
|
|
10817
11128
|
__decorate([ApiProperty({
|
|
10818
11129
|
type: "string",
|
|
10819
|
-
example: offerExample.offer.
|
|
10820
|
-
})], OfferDataResponse.prototype, "
|
|
11130
|
+
example: offerExample.offer.max_units
|
|
11131
|
+
})], OfferDataResponse.prototype, "max_units", void 0);
|
|
10821
11132
|
__decorate([ApiProperty({
|
|
10822
11133
|
type: "number",
|
|
10823
11134
|
example: offerExample.offer.start
|
|
@@ -11071,9 +11382,9 @@ __decorate([ApiProperty({
|
|
|
11071
11382
|
})], ValidateOfferRequest.prototype, "maker", void 0);
|
|
11072
11383
|
__decorate([ApiProperty({
|
|
11073
11384
|
type: "string",
|
|
11074
|
-
example: validateOfferExample.
|
|
11385
|
+
example: validateOfferExample.max_units,
|
|
11075
11386
|
required: false
|
|
11076
|
-
})], ValidateOfferRequest.prototype, "
|
|
11387
|
+
})], ValidateOfferRequest.prototype, "max_units", void 0);
|
|
11077
11388
|
__decorate([ApiProperty({
|
|
11078
11389
|
type: "number",
|
|
11079
11390
|
example: validateOfferExample.tick,
|
|
@@ -11207,7 +11518,7 @@ __decorate([ApiProperty({
|
|
|
11207
11518
|
__decorate([ApiProperty({
|
|
11208
11519
|
type: "string",
|
|
11209
11520
|
example: "369216000000000000000000"
|
|
11210
|
-
})], BookLevelResponse.prototype, "
|
|
11521
|
+
})], BookLevelResponse.prototype, "max_units", void 0);
|
|
11211
11522
|
__decorate([ApiProperty({
|
|
11212
11523
|
type: "number",
|
|
11213
11524
|
example: 5
|
|
@@ -12184,7 +12495,7 @@ async function getBook(params, db) {
|
|
|
12184
12495
|
levels_count: levels.length,
|
|
12185
12496
|
has_next_cursor: nextCursor != null,
|
|
12186
12497
|
first_level_tick: firstLevel?.tick ?? null,
|
|
12187
|
-
|
|
12498
|
+
first_level_max_units: firstLevel?.maxUnits.toString() ?? null,
|
|
12188
12499
|
first_level_count: firstLevel?.count ?? null
|
|
12189
12500
|
});
|
|
12190
12501
|
return success({
|
|
@@ -12318,7 +12629,6 @@ const assets = {
|
|
|
12318
12629
|
"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
|
|
12319
12630
|
"0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb",
|
|
12320
12631
|
"0x4200000000000000000000000000000000000006",
|
|
12321
|
-
"0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599",
|
|
12322
12632
|
"0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf",
|
|
12323
12633
|
"0xc1CBa3fCea344f92D9239c08C0568f6F2F0ee452",
|
|
12324
12634
|
"0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42"
|
|
@@ -12933,7 +13243,7 @@ function create$16(parameters) {
|
|
|
12933
13243
|
obligationId: obligationIdKeys.obligationId,
|
|
12934
13244
|
chainId: obligationIdKeys.chainId,
|
|
12935
13245
|
loanToken: obligations.loanToken,
|
|
12936
|
-
collaterals: sql`ARRAY_AGG(jsonb_build_object('asset', ${obligationCollateralsV2.asset}, 'oracle', ${obligationCollateralsV2.oracleAddress}, 'lltv', ${obligationCollateralsV2.lltv}))`.as("collaterals"),
|
|
13246
|
+
collaterals: sql`ARRAY_AGG(jsonb_build_object('asset', ${obligationCollateralsV2.asset}, 'oracle', ${obligationCollateralsV2.oracleAddress}, 'lltv', ${obligationCollateralsV2.lltv}::text, 'maxLif', ${obligationCollateralsV2.maxLif}::text))`.as("collaterals"),
|
|
12937
13247
|
maturity: obligations.maturity,
|
|
12938
13248
|
rcfThreshold: obligations.rcfThreshold,
|
|
12939
13249
|
askTick: sql`MAX(${bestQuotes.askTick})`.as("ask_tick"),
|
|
@@ -12966,7 +13276,8 @@ function create$16(parameters) {
|
|
|
12966
13276
|
collaterals: row.collaterals.sort((left, right) => left.asset.localeCompare(right.asset)).map((collateral) => from$16({
|
|
12967
13277
|
asset: collateral.asset,
|
|
12968
13278
|
oracle: collateral.oracle,
|
|
12969
|
-
lltv: from$17(BigInt(collateral.lltv))
|
|
13279
|
+
lltv: from$17(BigInt(collateral.lltv)),
|
|
13280
|
+
maxLif: BigInt(collateral.maxLif)
|
|
12970
13281
|
})),
|
|
12971
13282
|
maturity: row.maturity,
|
|
12972
13283
|
rcfThreshold: BigInt(row.rcfThreshold)
|
|
@@ -13235,11 +13546,11 @@ function offerBalanceTerm(balance, price, lltv) {
|
|
|
13235
13546
|
* @param lotLower - Lot lower bound (in assets).
|
|
13236
13547
|
* @param lotUpper - Lot upper bound (in assets).
|
|
13237
13548
|
* @param consumed - Group consumed amount (in obligation units).
|
|
13238
|
-
* @param
|
|
13549
|
+
* @param maxUnits - Offer obligation units.
|
|
13239
13550
|
*/
|
|
13240
|
-
function lotBalance(offerBalance, offset, positionConsumed, lotLower, lotUpper, consumed,
|
|
13551
|
+
function lotBalance(offerBalance, offset, positionConsumed, lotLower, lotUpper, consumed, maxUnits) {
|
|
13241
13552
|
const lotSize = sql`(COALESCE(${lotUpper}::numeric, 0) - COALESCE(${lotLower}::numeric, 0))`;
|
|
13242
|
-
return sql`GREATEST(0, LEAST(COALESCE(${offerBalance}, 0) + COALESCE(${offset}, 0) + COALESCE(${positionConsumed}, 0) - COALESCE(${lotLower}::numeric, 0), ${lotSize} - ${sql`CASE WHEN ${
|
|
13553
|
+
return sql`GREATEST(0, LEAST(COALESCE(${offerBalance}, 0) + COALESCE(${offset}, 0) + COALESCE(${positionConsumed}, 0) - COALESCE(${lotLower}::numeric, 0), ${lotSize} - ${sql`CASE WHEN ${maxUnits}::numeric > 0 THEN COALESCE(${consumed}::numeric, 0) * ${lotSize} / ${maxUnits}::numeric ELSE 0 END`}))`;
|
|
13243
13554
|
}
|
|
13244
13555
|
/**
|
|
13245
13556
|
* Callback contribution: amount contributed by one callback in loan terms.
|
|
@@ -13251,17 +13562,23 @@ function contribution(lotBalance, lotLower) {
|
|
|
13251
13562
|
return sql`CASE WHEN ${lotLower} IS NULL THEN 0 ELSE ${lotBalance} END`;
|
|
13252
13563
|
}
|
|
13253
13564
|
/**
|
|
13254
|
-
* Takeable amount in assets.
|
|
13255
|
-
*
|
|
13256
|
-
*
|
|
13257
|
-
*
|
|
13565
|
+
* Takeable amount in maker-side assets.
|
|
13566
|
+
* Buy offers use the floor maker-asset surface for remaining obligation units.
|
|
13567
|
+
* Sell offers use the ceil maker-asset surface for remaining obligation units.
|
|
13568
|
+
* The result is then compared with available (already in assets from lot balance).
|
|
13569
|
+
* @param maxUnits - Offer obligation units.
|
|
13258
13570
|
* @param consumed - Group consumed amount (in obligation units).
|
|
13259
13571
|
* @param available - Total available from callbacks/positions (in assets).
|
|
13260
13572
|
* @param price - Tick price (from tick_prices CTE).
|
|
13573
|
+
* @param buy - Offer side (`true` for buy, `false` for sell).
|
|
13261
13574
|
*/
|
|
13262
|
-
function takeable(
|
|
13575
|
+
function takeable(maxUnits, consumed, available, price, buy) {
|
|
13263
13576
|
const WAD_SQL = sql`(10::numeric ^ 18)`;
|
|
13264
|
-
|
|
13577
|
+
const remainingUnits = sql`GREATEST(COALESCE(${maxUnits}::numeric, 0) - COALESCE(${consumed}::numeric, 0), 0)`;
|
|
13578
|
+
return sql`GREATEST(0, LEAST(${sql`CASE WHEN ${buy}
|
|
13579
|
+
THEN TRUNC(${remainingUnits} * COALESCE(${price}::numeric, 0) / ${WAD_SQL})
|
|
13580
|
+
ELSE CEIL(${remainingUnits} * COALESCE(${price}::numeric, 0) / ${WAD_SQL})
|
|
13581
|
+
END`}, ${available}))`;
|
|
13265
13582
|
}
|
|
13266
13583
|
/** Precomputed tick→price lookup (all 991 ticks). */
|
|
13267
13584
|
const TICK_PRICES = Array.from({ length: TICK_RANGE + 1 }, (_, i) => [i, tickToPrice(i).toString()]);
|
|
@@ -13293,7 +13610,7 @@ function offerAvailabilityCTEs(params) {
|
|
|
13293
13610
|
return sql`
|
|
13294
13611
|
, group_winners AS (
|
|
13295
13612
|
SELECT DISTINCT ON (o.group_chain_id, o.group_maker, o.group_group, o.obligation_id, o.buy)
|
|
13296
|
-
o.group_chain_id, o.group_maker, o.group_group, o.obligation_id, o.buy, o.
|
|
13613
|
+
o.group_chain_id, o.group_maker, o.group_group, o.obligation_id, o.buy, o.max_units
|
|
13297
13614
|
FROM ${offers} o
|
|
13298
13615
|
LEFT JOIN ${validations} v
|
|
13299
13616
|
ON v.offer_hash = o.hash
|
|
@@ -13310,7 +13627,7 @@ function offerAvailabilityCTEs(params) {
|
|
|
13310
13627
|
ORDER BY
|
|
13311
13628
|
o.group_chain_id, o.group_maker, o.group_group, o.obligation_id, o.buy,
|
|
13312
13629
|
CASE WHEN o.buy THEN -o.tick ELSE o.tick END ASC,
|
|
13313
|
-
o.block_number ASC, o.
|
|
13630
|
+
o.block_number ASC, o.max_units DESC, o.hash ASC
|
|
13314
13631
|
),
|
|
13315
13632
|
relevant_positions AS (
|
|
13316
13633
|
SELECT DISTINCT c.position_chain_id, c.position_contract, c.position_user
|
|
@@ -13335,8 +13652,8 @@ function offerAvailabilityCTEs(params) {
|
|
|
13335
13652
|
COALESCE(
|
|
13336
13653
|
SUM(
|
|
13337
13654
|
CASE
|
|
13338
|
-
WHEN wo.
|
|
13339
|
-
THEN COALESCE(g.consumed::numeric, 0) * (l.upper::numeric - l.lower::numeric) / wo.
|
|
13655
|
+
WHEN wo.max_units::numeric > 0
|
|
13656
|
+
THEN COALESCE(g.consumed::numeric, 0) * (l.upper::numeric - l.lower::numeric) / wo.max_units::numeric
|
|
13340
13657
|
ELSE 0
|
|
13341
13658
|
END
|
|
13342
13659
|
) OVER (
|
|
@@ -13383,14 +13700,14 @@ function offerAvailabilityCTEs(params) {
|
|
|
13383
13700
|
src.obligation_id,
|
|
13384
13701
|
src.group_group,
|
|
13385
13702
|
src.consumed,
|
|
13386
|
-
src.
|
|
13703
|
+
src.max_units,
|
|
13387
13704
|
c.id AS callback_id,
|
|
13388
13705
|
c.position_chain_id,
|
|
13389
13706
|
c.position_contract,
|
|
13390
13707
|
c.position_user,
|
|
13391
13708
|
l.lower AS lot_lower,
|
|
13392
13709
|
l.upper AS lot_upper,
|
|
13393
|
-
${lotBalance(sql`vb.offer_balance`, sql`pos_offsets.total_offset`, sql`pc.consumed`, sql`l.lower`, sql`l.upper`, sql`src.consumed`, sql`src.
|
|
13710
|
+
${lotBalance(sql`vb.offer_balance`, sql`pos_offsets.total_offset`, sql`pc.consumed`, sql`l.lower`, sql`l.upper`, sql`src.consumed`, sql`src.max_units`)} AS lot_balance
|
|
13394
13711
|
FROM ${source} src
|
|
13395
13712
|
LEFT JOIN ${offersCallbacks} oc
|
|
13396
13713
|
ON oc.offer_hash = src.hash
|
|
@@ -13458,7 +13775,7 @@ function offerTakeabilityCTEs(params) {
|
|
|
13458
13775
|
offer_takeable AS (
|
|
13459
13776
|
SELECT src.hash, src.obligation_id,
|
|
13460
13777
|
COALESCE(oa.available, 0) AS available,
|
|
13461
|
-
${takeable(sql`src.
|
|
13778
|
+
${takeable(sql`src.max_units`, sql`src.consumed`, sql`COALESCE(oa.available, 0)`, sql`tp.price`, sql`src.buy`)} AS takeable
|
|
13462
13779
|
FROM ${source} src
|
|
13463
13780
|
LEFT JOIN offer_available oa ON oa.hash = src.hash AND oa.obligation_id = src.obligation_id
|
|
13464
13781
|
LEFT JOIN tick_prices tp ON tp.tick = src.tick
|
|
@@ -13555,8 +13872,8 @@ function create$15(config) {
|
|
|
13555
13872
|
jsonb_build_object(
|
|
13556
13873
|
'asset', ${obligationCollateralsV2.asset},
|
|
13557
13874
|
'oracle', ${obligationCollateralsV2.oracleAddress},
|
|
13558
|
-
'lltv', ${obligationCollateralsV2.lltv},
|
|
13559
|
-
'maxLif', ${obligationCollateralsV2.maxLif}
|
|
13875
|
+
'lltv', ${obligationCollateralsV2.lltv}::text,
|
|
13876
|
+
'maxLif', ${obligationCollateralsV2.maxLif}::text
|
|
13560
13877
|
)
|
|
13561
13878
|
),
|
|
13562
13879
|
'[]'::jsonb
|
|
@@ -13565,7 +13882,7 @@ function create$15(config) {
|
|
|
13565
13882
|
hash: offers.hash,
|
|
13566
13883
|
obligationId: offers.obligationId,
|
|
13567
13884
|
maker: offers.groupMaker,
|
|
13568
|
-
|
|
13885
|
+
maxUnits: offers.maxUnits,
|
|
13569
13886
|
tick: offers.tick,
|
|
13570
13887
|
maturity: offers.maturity,
|
|
13571
13888
|
rcfThreshold: obligations.rcfThreshold,
|
|
@@ -13588,7 +13905,7 @@ function create$15(config) {
|
|
|
13588
13905
|
hash: row.hash,
|
|
13589
13906
|
obligationId: row.obligationId,
|
|
13590
13907
|
maker: row.maker,
|
|
13591
|
-
|
|
13908
|
+
maxUnits: BigInt(row.maxUnits),
|
|
13592
13909
|
tick: row.tick,
|
|
13593
13910
|
maturity: from$15(row.maturity),
|
|
13594
13911
|
rcfThreshold: BigInt(row.rcfThreshold),
|
|
@@ -13603,7 +13920,7 @@ function create$15(config) {
|
|
|
13603
13920
|
asset: c.asset,
|
|
13604
13921
|
oracle: c.oracle,
|
|
13605
13922
|
lltv: BigInt(c.lltv),
|
|
13606
|
-
maxLif: BigInt(c.maxLif
|
|
13923
|
+
maxLif: BigInt(c.maxLif)
|
|
13607
13924
|
})).sort((a, b) => a.asset.toLowerCase().localeCompare(b.asset.toLowerCase())),
|
|
13608
13925
|
callback: {
|
|
13609
13926
|
address: row.callbackAddress,
|
|
@@ -13859,8 +14176,8 @@ async function getOffersQuery(db, parameters) {
|
|
|
13859
14176
|
COALESCE(jsonb_agg(jsonb_build_object(
|
|
13860
14177
|
'asset', oc.asset,
|
|
13861
14178
|
'oracle', oc.oracle_address,
|
|
13862
|
-
'lltv', oc.lltv,
|
|
13863
|
-
'maxLif', oc.max_lif
|
|
14179
|
+
'lltv', oc.lltv::text,
|
|
14180
|
+
'maxLif', oc.max_lif::text
|
|
13864
14181
|
) ORDER BY oc.asset), '[]'::jsonb) AS collaterals
|
|
13865
14182
|
FROM ${obligationIdKeys} oia
|
|
13866
14183
|
JOIN ${obligationCollateralsV2} oc
|
|
@@ -13877,7 +14194,7 @@ async function getOffersQuery(db, parameters) {
|
|
|
13877
14194
|
mo.hash,
|
|
13878
14195
|
mo.obligation_id,
|
|
13879
14196
|
mo.group_maker,
|
|
13880
|
-
mo.
|
|
14197
|
+
mo.max_units,
|
|
13881
14198
|
mo.consumed,
|
|
13882
14199
|
mo.tick,
|
|
13883
14200
|
mo.maturity,
|
|
@@ -13909,11 +14226,14 @@ async function getOffersQuery(db, parameters) {
|
|
|
13909
14226
|
ORDER BY mo.hash ASC, mo.obligation_id ASC;
|
|
13910
14227
|
`)).rows.map((row) => {
|
|
13911
14228
|
const receiverIfMakerIsSeller = (row.receiver_if_maker_is_seller ?? row.group_maker).toLowerCase();
|
|
14229
|
+
const maxUnits = BigInt(row.max_units ?? 0);
|
|
14230
|
+
const consumed = BigInt(row.consumed ?? 0);
|
|
14231
|
+
const remainingUnits = maxUnits > consumed ? maxUnits - consumed : 0n;
|
|
13912
14232
|
return {
|
|
13913
14233
|
hash: row.hash,
|
|
13914
14234
|
obligationId: row.obligation_id,
|
|
13915
14235
|
maker: row.group_maker,
|
|
13916
|
-
|
|
14236
|
+
maxUnits,
|
|
13917
14237
|
tick: row.tick,
|
|
13918
14238
|
maturity: row.maturity,
|
|
13919
14239
|
expiry: row.expiry,
|
|
@@ -13928,7 +14248,7 @@ async function getOffersQuery(db, parameters) {
|
|
|
13928
14248
|
asset: c.asset,
|
|
13929
14249
|
oracle: c.oracle,
|
|
13930
14250
|
lltv: BigInt(c.lltv),
|
|
13931
|
-
maxLif: BigInt(c.maxLif
|
|
14251
|
+
maxLif: BigInt(c.maxLif)
|
|
13932
14252
|
})).sort((a, b) => a.asset.toLowerCase().localeCompare(b.asset.toLowerCase())),
|
|
13933
14253
|
callback: {
|
|
13934
14254
|
address: row.callback_address,
|
|
@@ -13936,9 +14256,9 @@ async function getOffersQuery(db, parameters) {
|
|
|
13936
14256
|
},
|
|
13937
14257
|
receiverIfMakerIsSeller,
|
|
13938
14258
|
exitOnly: row.exit_only,
|
|
13939
|
-
consumed
|
|
14259
|
+
consumed,
|
|
13940
14260
|
available: BigInt(String(row.available ?? "0").split(".")[0] ?? "0"),
|
|
13941
|
-
takeable:
|
|
14261
|
+
takeable: assetsToUnits(BigInt(String(row.takeable ?? "0").split(".")[0] ?? "0"), row.tick, row.buy, remainingUnits),
|
|
13942
14262
|
blockNumber: row.block_number,
|
|
13943
14263
|
root: row.tree_root ? row.tree_root.toLowerCase() : void 0,
|
|
13944
14264
|
signature: row.root_signature ? row.root_signature.toLowerCase() : void 0,
|
|
@@ -13982,7 +14302,8 @@ async function getOffers$1(queryParameters, db) {
|
|
|
13982
14302
|
side: query.side,
|
|
13983
14303
|
obligationId: query.obligation_id,
|
|
13984
14304
|
cursor: query.cursor,
|
|
13985
|
-
limit: query.limit
|
|
14305
|
+
limit: query.limit,
|
|
14306
|
+
requirePositiveTakeableAssets: true
|
|
13986
14307
|
});
|
|
13987
14308
|
logger.debug({
|
|
13988
14309
|
service: "api_controller",
|
|
@@ -14229,6 +14550,7 @@ function createApp(parameters) {
|
|
|
14229
14550
|
origin: "*",
|
|
14230
14551
|
exposeHeaders: ["x-request-id"]
|
|
14231
14552
|
}));
|
|
14553
|
+
app.get("/", (c) => c.redirect("/docs"));
|
|
14232
14554
|
app.get("/v1/offers", async (c) => {
|
|
14233
14555
|
const { statusCode, body } = await services.getOffers(c.req.query());
|
|
14234
14556
|
return c.json(body, statusCode);
|
|
@@ -14416,7 +14738,7 @@ async function getOffers(apiClient, parameters) {
|
|
|
14416
14738
|
return {
|
|
14417
14739
|
...fromSnakeCase$1({
|
|
14418
14740
|
maker: offerData.maker,
|
|
14419
|
-
|
|
14741
|
+
max_units: offerData.max_units,
|
|
14420
14742
|
tick: offerData.tick,
|
|
14421
14743
|
maturity: from$15(offerData.obligation.maturity),
|
|
14422
14744
|
rcf_threshold: offerData.obligation.rcf_threshold,
|
|
@@ -14790,7 +15112,7 @@ function create$11(config) {
|
|
|
14790
15112
|
const db = config.db;
|
|
14791
15113
|
const logger = getLogger();
|
|
14792
15114
|
const getOffers = async (parameters) => {
|
|
14793
|
-
const { side, obligationId, cursor: cursorString } = parameters;
|
|
15115
|
+
const { side, obligationId, cursor: cursorString, requirePositiveTakeableAssets = false } = parameters;
|
|
14794
15116
|
const requestedLimit = parameters.limit ?? DEFAULT_LIMIT$2;
|
|
14795
15117
|
const priceSortDirection = side === "sell" ? "asc" : "desc";
|
|
14796
15118
|
const inputCursor = Cursor.decode(cursorString, logger);
|
|
@@ -14811,7 +15133,8 @@ function create$11(config) {
|
|
|
14811
15133
|
now,
|
|
14812
15134
|
priceSortDirection,
|
|
14813
15135
|
cursor: inputCursor,
|
|
14814
|
-
limit: Math.min(requestedLimit, MAX_TOTAL_OFFERS - previouslyReturned)
|
|
15136
|
+
limit: Math.min(requestedLimit, MAX_TOTAL_OFFERS - previouslyReturned),
|
|
15137
|
+
requirePositiveTakeableAssets
|
|
14815
15138
|
});
|
|
14816
15139
|
const lastReturnedOffer = rows[rows.length - 1];
|
|
14817
15140
|
const newTotalReturned = previouslyReturned + rows.length;
|
|
@@ -14843,16 +15166,16 @@ function create$11(config) {
|
|
|
14843
15166
|
for (const row of rows) {
|
|
14844
15167
|
const existing = tickMap.get(row.tick);
|
|
14845
15168
|
if (existing) {
|
|
14846
|
-
existing.
|
|
15169
|
+
existing.maxUnits += row.takeable;
|
|
14847
15170
|
existing.count += 1;
|
|
14848
15171
|
} else tickMap.set(row.tick, {
|
|
14849
|
-
|
|
15172
|
+
maxUnits: row.takeable,
|
|
14850
15173
|
count: 1
|
|
14851
15174
|
});
|
|
14852
15175
|
}
|
|
14853
15176
|
const levels = Array.from(tickMap.entries()).map(([tick, level]) => ({
|
|
14854
15177
|
tick,
|
|
14855
|
-
|
|
15178
|
+
maxUnits: level.maxUnits,
|
|
14856
15179
|
count: level.count
|
|
14857
15180
|
}));
|
|
14858
15181
|
levels.sort((a, b) => tickSortDirection === "asc" ? a.tick - b.tick : b.tick - a.tick);
|
|
@@ -14869,15 +15192,15 @@ function create$11(config) {
|
|
|
14869
15192
|
}
|
|
14870
15193
|
/** Get offers with computed takeable based on lot balance. */
|
|
14871
15194
|
async function _getOffers(db, params) {
|
|
14872
|
-
const { obligationId, side, now, priceSortDirection, cursor, limit } = params;
|
|
15195
|
+
const { obligationId, side, now, priceSortDirection, cursor, limit, requirePositiveTakeableAssets } = params;
|
|
14873
15196
|
const raw = await db.execute(sql`
|
|
14874
15197
|
WITH collats AS MATERIALIZED (
|
|
14875
15198
|
SELECT oia.obligation_id,
|
|
14876
15199
|
COALESCE(jsonb_agg(jsonb_build_object(
|
|
14877
15200
|
'asset', oc.asset,
|
|
14878
15201
|
'oracle', oc.oracle_address,
|
|
14879
|
-
'lltv', oc.lltv,
|
|
14880
|
-
'maxLif', oc.max_lif
|
|
15202
|
+
'lltv', oc.lltv::text,
|
|
15203
|
+
'maxLif', oc.max_lif::text
|
|
14881
15204
|
) ORDER BY oc.asset), '[]'::jsonb) AS collaterals
|
|
14882
15205
|
FROM ${obligationIdKeys} oia
|
|
14883
15206
|
JOIN ${obligationCollateralsV2} oc
|
|
@@ -14902,7 +15225,7 @@ async function _getOffers(db, params) {
|
|
|
14902
15225
|
AND (s.code IS NULL OR s.code = ${Status.VALID})
|
|
14903
15226
|
ORDER BY
|
|
14904
15227
|
o.group_chain_id, o.group_maker, o."group_group",
|
|
14905
|
-
CASE WHEN o.buy THEN -o.tick ELSE o.tick END ASC, o.block_number ASC, o.
|
|
15228
|
+
CASE WHEN o.buy THEN -o.tick ELSE o.tick END ASC, o.block_number ASC, o.max_units DESC, o.hash ASC
|
|
14906
15229
|
),
|
|
14907
15230
|
enriched AS (
|
|
14908
15231
|
SELECT
|
|
@@ -14911,7 +15234,7 @@ async function _getOffers(db, params) {
|
|
|
14911
15234
|
CASE WHEN ${priceSortDirection === "asc" ? sql`TRUE` : sql`FALSE`}
|
|
14912
15235
|
THEN w.tick ELSE -w.tick END AS tick_norm,
|
|
14913
15236
|
w.block_number AS block_norm,
|
|
14914
|
-
-w.
|
|
15237
|
+
-w.max_units AS max_units_norm,
|
|
14915
15238
|
w.hash AS hash_norm
|
|
14916
15239
|
FROM winners w
|
|
14917
15240
|
JOIN ${groups} g
|
|
@@ -14932,24 +15255,34 @@ async function _getOffers(db, params) {
|
|
|
14932
15255
|
SELECT e.*, COALESCE(ot.available, 0) AS available, ot.takeable
|
|
14933
15256
|
FROM enriched e
|
|
14934
15257
|
JOIN offer_takeable ot ON ot.hash = e.hash AND ot.obligation_id = e.obligation_id
|
|
14935
|
-
WHERE
|
|
15258
|
+
WHERE (
|
|
15259
|
+
ot.takeable > 0
|
|
15260
|
+
OR (
|
|
15261
|
+
COALESCE(e.max_units::numeric, 0) > COALESCE(e.consumed::numeric, 0)
|
|
15262
|
+
AND (
|
|
15263
|
+
e.tick = 0
|
|
15264
|
+
OR (e.buy AND e.tick < ${TICK_RANGE})
|
|
15265
|
+
)
|
|
15266
|
+
)
|
|
15267
|
+
)
|
|
15268
|
+
${requirePositiveTakeableAssets ? sql`AND TRUNC(COALESCE(ot.takeable, 0)::numeric) > 0` : sql``}
|
|
14936
15269
|
${cursor != null ? sql`
|
|
14937
|
-
AND (e.tick_norm, e.block_norm, e.
|
|
15270
|
+
AND (e.tick_norm, e.block_norm, e.max_units_norm, e.hash_norm)
|
|
14938
15271
|
> (
|
|
14939
15272
|
CASE WHEN ${priceSortDirection === "asc" ? sql`TRUE` : sql`FALSE`}
|
|
14940
15273
|
THEN ${cursor.tick}::integer ELSE -${cursor.tick}::integer END,
|
|
14941
15274
|
${cursor.blockNumber},
|
|
14942
|
-
-${cursor.
|
|
15275
|
+
-${cursor.maxUnits}::numeric,
|
|
14943
15276
|
${cursor.hash}
|
|
14944
15277
|
)` : sql``}
|
|
14945
|
-
ORDER BY e.tick ${priceSortDirection === "asc" ? sql`ASC` : sql`DESC`}, e.block_number ASC, e.
|
|
15278
|
+
ORDER BY e.tick ${priceSortDirection === "asc" ? sql`ASC` : sql`DESC`}, e.block_number ASC, e.max_units DESC, e.hash ASC
|
|
14946
15279
|
LIMIT ${limit}
|
|
14947
15280
|
)
|
|
14948
15281
|
SELECT
|
|
14949
15282
|
p.hash,
|
|
14950
15283
|
p.obligation_id,
|
|
14951
15284
|
p.group_maker,
|
|
14952
|
-
p.
|
|
15285
|
+
p.max_units,
|
|
14953
15286
|
p.consumed,
|
|
14954
15287
|
p.tick,
|
|
14955
15288
|
p.maturity,
|
|
@@ -14979,17 +15312,20 @@ async function _getOffers(db, params) {
|
|
|
14979
15312
|
ORDER BY
|
|
14980
15313
|
p.tick ${priceSortDirection === "asc" ? sql`ASC` : sql`DESC`},
|
|
14981
15314
|
p.block_number ASC,
|
|
14982
|
-
p.
|
|
15315
|
+
p.max_units DESC,
|
|
14983
15316
|
p.hash ASC;
|
|
14984
15317
|
`);
|
|
14985
15318
|
return {
|
|
14986
15319
|
rows: raw.rows.map((row) => {
|
|
14987
15320
|
const receiverIfMakerIsSeller = (row.receiver_if_maker_is_seller ?? row.group_maker).toLowerCase();
|
|
15321
|
+
const maxUnits = BigInt(row.max_units ?? 0);
|
|
15322
|
+
const consumed = BigInt(row.consumed ?? 0);
|
|
15323
|
+
const remainingUnits = maxUnits > consumed ? maxUnits - consumed : 0n;
|
|
14988
15324
|
return {
|
|
14989
15325
|
hash: row.hash,
|
|
14990
15326
|
obligationId: row.obligation_id,
|
|
14991
15327
|
maker: row.group_maker,
|
|
14992
|
-
|
|
15328
|
+
maxUnits,
|
|
14993
15329
|
tick: row.tick,
|
|
14994
15330
|
maturity: row.maturity,
|
|
14995
15331
|
expiry: row.expiry,
|
|
@@ -15004,7 +15340,7 @@ async function _getOffers(db, params) {
|
|
|
15004
15340
|
asset: c.asset,
|
|
15005
15341
|
oracle: c.oracle,
|
|
15006
15342
|
lltv: BigInt(c.lltv),
|
|
15007
|
-
maxLif: BigInt(c.maxLif
|
|
15343
|
+
maxLif: BigInt(c.maxLif)
|
|
15008
15344
|
})),
|
|
15009
15345
|
callback: {
|
|
15010
15346
|
address: row.callback_address,
|
|
@@ -15013,9 +15349,9 @@ async function _getOffers(db, params) {
|
|
|
15013
15349
|
receiverIfMakerIsSeller,
|
|
15014
15350
|
exitOnly: row.exit_only,
|
|
15015
15351
|
blockNumber: row.block_number,
|
|
15016
|
-
consumed
|
|
15352
|
+
consumed,
|
|
15017
15353
|
available: BigInt(String(row.available ?? "0").split(".")[0] ?? "0"),
|
|
15018
|
-
takeable:
|
|
15354
|
+
takeable: assetsToUnits(BigInt(String(row.takeable).split(".")[0] ?? "0"), row.tick, row.buy, remainingUnits),
|
|
15019
15355
|
root: row.tree_root ? row.tree_root.toLowerCase() : void 0,
|
|
15020
15356
|
signature: row.root_signature ? row.root_signature.toLowerCase() : void 0,
|
|
15021
15357
|
proof: row.proof_nodes ? splitProofs(row.proof_nodes) : void 0
|
|
@@ -15031,7 +15367,7 @@ let Cursor;
|
|
|
15031
15367
|
side,
|
|
15032
15368
|
tick: row.tick,
|
|
15033
15369
|
blockNumber: row.blockNumber,
|
|
15034
|
-
|
|
15370
|
+
maxUnits: row.maxUnits.toString(),
|
|
15035
15371
|
hash: row.hash,
|
|
15036
15372
|
totalReturned,
|
|
15037
15373
|
now
|
|
@@ -15042,7 +15378,7 @@ let Cursor;
|
|
|
15042
15378
|
if (cursorString == null) return null;
|
|
15043
15379
|
try {
|
|
15044
15380
|
const v = JSON.parse(Buffer.from(cursorString, "base64url").toString("utf8"));
|
|
15045
|
-
if ((v?.side === "buy" || v?.side === "sell") && typeof v?.tick === "number" && Number.isInteger(v.tick) && typeof v?.blockNumber === "number" && Number.isInteger(v.blockNumber) && typeof v?.
|
|
15381
|
+
if ((v?.side === "buy" || v?.side === "sell") && typeof v?.tick === "number" && Number.isInteger(v.tick) && typeof v?.blockNumber === "number" && Number.isInteger(v.blockNumber) && typeof v?.maxUnits === "string" && /^-?\d+$/.test(v.maxUnits) && isHex(v?.hash) && typeof v?.totalReturned === "number" && Number.isInteger(v.totalReturned) && typeof v?.now === "number" && Number.isInteger(v.now)) return v;
|
|
15046
15382
|
throw new Error("Invalid cursor");
|
|
15047
15383
|
} catch {
|
|
15048
15384
|
logger.error({
|
|
@@ -15094,7 +15430,10 @@ let LevelCursor;
|
|
|
15094
15430
|
function create$10(db) {
|
|
15095
15431
|
return {
|
|
15096
15432
|
upsert: async (inputs) => {
|
|
15097
|
-
if (inputs.length === 0) return
|
|
15433
|
+
if (inputs.length === 0) return {
|
|
15434
|
+
callbacksInserted: 0,
|
|
15435
|
+
offersCallbacksInserted: 0
|
|
15436
|
+
};
|
|
15098
15437
|
const idCache = /* @__PURE__ */ new Map();
|
|
15099
15438
|
const seenCallbackIds = /* @__PURE__ */ new Set();
|
|
15100
15439
|
const callbacksRows = [];
|
|
@@ -15134,7 +15473,10 @@ function create$10(db) {
|
|
|
15134
15473
|
});
|
|
15135
15474
|
}
|
|
15136
15475
|
}
|
|
15137
|
-
if (offersCallbacksRows.length === 0) return
|
|
15476
|
+
if (offersCallbacksRows.length === 0) return {
|
|
15477
|
+
callbacksInserted: 0,
|
|
15478
|
+
offersCallbacksInserted: 0
|
|
15479
|
+
};
|
|
15138
15480
|
const offerHashes = [...new Set(offersCallbacksRows.map((r) => r.offerHash))];
|
|
15139
15481
|
const existingOffers = await db.select({
|
|
15140
15482
|
hash: offers.hash,
|
|
@@ -15142,10 +15484,25 @@ function create$10(db) {
|
|
|
15142
15484
|
}).from(offers).where(inArray(offers.hash, offerHashes));
|
|
15143
15485
|
const existingKeys = new Set(existingOffers.map((r) => `${String(r.hash).toLowerCase()}:${String(r.obligationId).toLowerCase()}`));
|
|
15144
15486
|
const filteredOffersCallbacksRows = offersCallbacksRows.filter((r) => existingKeys.has(`${r.offerHash}:${r.obligationId}`));
|
|
15145
|
-
if (filteredOffersCallbacksRows.length === 0) return
|
|
15146
|
-
|
|
15147
|
-
|
|
15148
|
-
|
|
15487
|
+
if (filteredOffersCallbacksRows.length === 0) return {
|
|
15488
|
+
callbacksInserted: 0,
|
|
15489
|
+
offersCallbacksInserted: 0
|
|
15490
|
+
};
|
|
15491
|
+
return await db.transaction(async (dbTx) => {
|
|
15492
|
+
let callbacksInserted = 0;
|
|
15493
|
+
for (const batch of batch$1(callbacksRows, DEFAULT_BATCH_SIZE$1)) {
|
|
15494
|
+
const inserted = await dbTx.insert(callbacks).values(batch).onConflictDoNothing().returning();
|
|
15495
|
+
callbacksInserted += inserted.length;
|
|
15496
|
+
}
|
|
15497
|
+
let offersCallbacksInserted = 0;
|
|
15498
|
+
for (const batch of batch$1(filteredOffersCallbacksRows, DEFAULT_BATCH_SIZE$1)) {
|
|
15499
|
+
const inserted = await dbTx.insert(offersCallbacks).values(batch).onConflictDoNothing().returning();
|
|
15500
|
+
offersCallbacksInserted += inserted.length;
|
|
15501
|
+
}
|
|
15502
|
+
return {
|
|
15503
|
+
callbacksInserted,
|
|
15504
|
+
offersCallbacksInserted
|
|
15505
|
+
};
|
|
15149
15506
|
});
|
|
15150
15507
|
},
|
|
15151
15508
|
delete: async ({ offers }) => {
|
|
@@ -15161,7 +15518,10 @@ function create$10(db) {
|
|
|
15161
15518
|
function create$9(db) {
|
|
15162
15519
|
return {
|
|
15163
15520
|
create: async (events) => {
|
|
15164
|
-
if (events.length === 0) return
|
|
15521
|
+
if (events.length === 0) return {
|
|
15522
|
+
groupsInserted: 0,
|
|
15523
|
+
consumedEventsInserted: 0
|
|
15524
|
+
};
|
|
15165
15525
|
const groups$3 = /* @__PURE__ */ new Map();
|
|
15166
15526
|
for (const event of events) {
|
|
15167
15527
|
const groupId = `${event.chainId}-${event.maker}-${event.group}`.toLowerCase();
|
|
@@ -15172,7 +15532,7 @@ function create$9(db) {
|
|
|
15172
15532
|
blockNumber: event.blockNumber
|
|
15173
15533
|
});
|
|
15174
15534
|
}
|
|
15175
|
-
await db.transaction(async (dbTx) => {
|
|
15535
|
+
return await db.transaction(async (dbTx) => {
|
|
15176
15536
|
const groupsRows = Array.from(groups$3.values()).map((group) => ({
|
|
15177
15537
|
chainId: group.chainId,
|
|
15178
15538
|
maker: group.maker.toLowerCase(),
|
|
@@ -15180,7 +15540,11 @@ function create$9(db) {
|
|
|
15180
15540
|
consumed: "0",
|
|
15181
15541
|
blockNumber: group.blockNumber
|
|
15182
15542
|
}));
|
|
15183
|
-
|
|
15543
|
+
let groupsInserted = 0;
|
|
15544
|
+
for (const batch of batch$1(groupsRows, DEFAULT_BATCH_SIZE$1)) {
|
|
15545
|
+
const inserted = await dbTx.insert(groups).values(batch).onConflictDoNothing().returning();
|
|
15546
|
+
groupsInserted += inserted.length;
|
|
15547
|
+
}
|
|
15184
15548
|
const eventsRows = events.map((event) => ({
|
|
15185
15549
|
eventId: event.id,
|
|
15186
15550
|
chainId: event.chainId,
|
|
@@ -15189,7 +15553,15 @@ function create$9(db) {
|
|
|
15189
15553
|
amount: event.amount.toString(),
|
|
15190
15554
|
blockNumber: event.blockNumber
|
|
15191
15555
|
}));
|
|
15192
|
-
|
|
15556
|
+
let consumedEventsInserted = 0;
|
|
15557
|
+
for (const batch of batch$1(eventsRows, DEFAULT_BATCH_SIZE$1)) {
|
|
15558
|
+
const inserted = await dbTx.insert(consumedEvents).values(batch).onConflictDoNothing().returning();
|
|
15559
|
+
consumedEventsInserted += inserted.length;
|
|
15560
|
+
}
|
|
15561
|
+
return {
|
|
15562
|
+
groupsInserted,
|
|
15563
|
+
consumedEventsInserted
|
|
15564
|
+
};
|
|
15193
15565
|
});
|
|
15194
15566
|
},
|
|
15195
15567
|
delete: async (parameters) => {
|
|
@@ -15213,7 +15585,7 @@ function compositeKey(g) {
|
|
|
15213
15585
|
function create$8(db) {
|
|
15214
15586
|
return {
|
|
15215
15587
|
create: async (groups$1) => {
|
|
15216
|
-
if (groups$1.length === 0) return;
|
|
15588
|
+
if (groups$1.length === 0) return 0;
|
|
15217
15589
|
const rows = groups$1.map((group) => ({
|
|
15218
15590
|
chainId: group.chainId,
|
|
15219
15591
|
maker: group.maker.toLowerCase(),
|
|
@@ -15221,7 +15593,12 @@ function create$8(db) {
|
|
|
15221
15593
|
consumed: (group.consumed ?? 0n).toString(),
|
|
15222
15594
|
blockNumber: group.blockNumber
|
|
15223
15595
|
}));
|
|
15224
|
-
|
|
15596
|
+
let insertedCount = 0;
|
|
15597
|
+
for (const batch of batch$1(rows, DEFAULT_BATCH_SIZE$1)) {
|
|
15598
|
+
const inserted = await db.insert(groups).values(batch).onConflictDoNothing().returning();
|
|
15599
|
+
insertedCount += inserted.length;
|
|
15600
|
+
}
|
|
15601
|
+
return insertedCount;
|
|
15225
15602
|
},
|
|
15226
15603
|
exists: async (groups$2) => {
|
|
15227
15604
|
if (groups$2.length === 0) return [];
|
|
@@ -15262,7 +15639,10 @@ function create$7(db) {
|
|
|
15262
15639
|
}));
|
|
15263
15640
|
},
|
|
15264
15641
|
create: async (parameters) => {
|
|
15265
|
-
if (parameters.length === 0) return
|
|
15642
|
+
if (parameters.length === 0) return {
|
|
15643
|
+
lotsPositionsInserted: 0,
|
|
15644
|
+
lotsInserted: 0
|
|
15645
|
+
};
|
|
15266
15646
|
const lotsByKey = /* @__PURE__ */ new Map();
|
|
15267
15647
|
for (const offer of parameters) {
|
|
15268
15648
|
const key = `${offer.positionChainId}-${offer.positionContract}-${offer.positionUser}-${offer.group}-${offer.obligationId}`.toLowerCase();
|
|
@@ -15280,7 +15660,10 @@ function create$7(db) {
|
|
|
15280
15660
|
const groupKey = `${offer.positionChainId}-${offer.positionUser.toLowerCase()}-${offer.group.toLowerCase()}`;
|
|
15281
15661
|
if (!existingGroupKeys.has(groupKey)) lotsByKey.delete(key);
|
|
15282
15662
|
}
|
|
15283
|
-
if (lotsByKey.size === 0) return
|
|
15663
|
+
if (lotsByKey.size === 0) return {
|
|
15664
|
+
lotsPositionsInserted: 0,
|
|
15665
|
+
lotsInserted: 0
|
|
15666
|
+
};
|
|
15284
15667
|
const positionsByKey = /* @__PURE__ */ new Map();
|
|
15285
15668
|
for (const offer of lotsByKey.values()) {
|
|
15286
15669
|
const posKey = `${offer.positionChainId}-${offer.positionContract}-${offer.positionUser}`.toLowerCase();
|
|
@@ -15291,12 +15674,17 @@ function create$7(db) {
|
|
|
15291
15674
|
positionTypeId: offer.positionTypeId
|
|
15292
15675
|
});
|
|
15293
15676
|
}
|
|
15294
|
-
|
|
15677
|
+
let lotsPositionsInserted = 0;
|
|
15678
|
+
for (const row of positionsByKey.values()) {
|
|
15679
|
+
const inserted = await db.insert(lotsPositions).values(row).onConflictDoNothing().returning();
|
|
15680
|
+
lotsPositionsInserted += inserted.length;
|
|
15681
|
+
}
|
|
15682
|
+
let lotsInserted = 0;
|
|
15295
15683
|
for (const offer of lotsByKey.values()) if ((await db.select().from(lots).where(and(eq(lots.chainId, offer.positionChainId), eq(lots.contract, offer.positionContract.toLowerCase()), eq(lots.user, offer.positionUser.toLowerCase()), eq(lots.group, offer.group.toLowerCase()), eq(lots.obligationId, offer.obligationId.toLowerCase()))).limit(1)).length === 0) {
|
|
15296
15684
|
const maxUpperResult = await db.select({ maxUpper: sql`COALESCE(MAX(${lots.upper}::numeric), 0)` }).from(lots).where(and(eq(lots.chainId, offer.positionChainId), eq(lots.contract, offer.positionContract.toLowerCase()), eq(lots.user, offer.positionUser.toLowerCase()), eq(lots.obligationId, offer.obligationId.toLowerCase())));
|
|
15297
15685
|
const newLower = BigInt(maxUpperResult[0]?.maxUpper ?? "0");
|
|
15298
15686
|
const newUpper = newLower + offer.size;
|
|
15299
|
-
await db.insert(lots).values({
|
|
15687
|
+
const inserted = await db.insert(lots).values({
|
|
15300
15688
|
chainId: offer.positionChainId,
|
|
15301
15689
|
user: offer.positionUser.toLowerCase(),
|
|
15302
15690
|
contract: offer.positionContract.toLowerCase(),
|
|
@@ -15304,8 +15692,13 @@ function create$7(db) {
|
|
|
15304
15692
|
obligationId: offer.obligationId.toLowerCase(),
|
|
15305
15693
|
lower: newLower.toString(),
|
|
15306
15694
|
upper: newUpper.toString()
|
|
15307
|
-
});
|
|
15695
|
+
}).returning();
|
|
15696
|
+
lotsInserted += inserted.length;
|
|
15308
15697
|
}
|
|
15698
|
+
return {
|
|
15699
|
+
lotsPositionsInserted,
|
|
15700
|
+
lotsInserted
|
|
15701
|
+
};
|
|
15309
15702
|
}
|
|
15310
15703
|
};
|
|
15311
15704
|
}
|
|
@@ -15327,7 +15720,7 @@ function create$6(db) {
|
|
|
15327
15720
|
chainId: obligationIdKeys.chainId,
|
|
15328
15721
|
morphoV2: obligationIdKeys.morphoV2,
|
|
15329
15722
|
loanToken: obligations.loanToken,
|
|
15330
|
-
collaterals: sql`ARRAY_AGG(jsonb_build_object('asset', ${obligationCollateralsV2.asset}, 'oracle', ${obligationCollateralsV2.oracleAddress}, 'lltv', ${obligationCollateralsV2.lltv}, 'maxLif', ${obligationCollateralsV2.maxLif}))`.as("collaterals"),
|
|
15723
|
+
collaterals: sql`ARRAY_AGG(jsonb_build_object('asset', ${obligationCollateralsV2.asset}, 'oracle', ${obligationCollateralsV2.oracleAddress}, 'lltv', ${obligationCollateralsV2.lltv}::text, 'maxLif', ${obligationCollateralsV2.maxLif}::text))`.as("collaterals"),
|
|
15331
15724
|
maturity: obligations.maturity,
|
|
15332
15725
|
rcfThreshold: obligations.rcfThreshold
|
|
15333
15726
|
}).from(obligationIdKeys).innerJoin(obligations, eq(obligationIdKeys.obligationKey, obligations.obligationKey)).innerJoin(obligationCollateralsV2, eq(obligations.obligationKey, obligationCollateralsV2.obligationKey)).groupBy(obligationIdKeys.obligationId, obligationIdKeys.chainId, obligationIdKeys.morphoV2, obligations.loanToken, obligations.maturity, obligations.rcfThreshold).where(and(chainIds !== void 0 && chainIds.length > 0 ? inArray(obligationIdKeys.chainId, chainIds) : void 0, gte(obligations.maturity, now$1))).orderBy(asc(obligationIdKeys.obligationId))).map((row) => ({
|
|
@@ -15340,7 +15733,7 @@ function create$6(db) {
|
|
|
15340
15733
|
asset: collateral.asset,
|
|
15341
15734
|
oracle: collateral.oracle,
|
|
15342
15735
|
lltv: from$17(BigInt(collateral.lltv)),
|
|
15343
|
-
maxLif: BigInt(collateral.maxLif
|
|
15736
|
+
maxLif: BigInt(collateral.maxLif)
|
|
15344
15737
|
})),
|
|
15345
15738
|
maturity: row.maturity,
|
|
15346
15739
|
rcfThreshold: BigInt(row.rcfThreshold)
|
|
@@ -15348,7 +15741,11 @@ function create$6(db) {
|
|
|
15348
15741
|
}));
|
|
15349
15742
|
},
|
|
15350
15743
|
create: async (obligations$1) => {
|
|
15351
|
-
if (obligations$1.length === 0) return
|
|
15744
|
+
if (obligations$1.length === 0) return {
|
|
15745
|
+
obligationsInserted: 0,
|
|
15746
|
+
obligationIdKeysInserted: 0,
|
|
15747
|
+
obligationCollateralsInserted: 0
|
|
15748
|
+
};
|
|
15352
15749
|
const obligationsByKey = /* @__PURE__ */ new Map();
|
|
15353
15750
|
const obligationIdKeysById = /* @__PURE__ */ new Map();
|
|
15354
15751
|
for (const input of obligations$1) {
|
|
@@ -15358,32 +15755,49 @@ function create$6(db) {
|
|
|
15358
15755
|
if (!obligationIdKeysById.has(obligationId)) obligationIdKeysById.set(obligationId, input);
|
|
15359
15756
|
}
|
|
15360
15757
|
try {
|
|
15361
|
-
await db.transaction(async (dbTx) => {
|
|
15758
|
+
return await db.transaction(async (dbTx) => {
|
|
15362
15759
|
const obligationRows = Array.from(obligationsByKey.entries()).map(([obligationKey, item]) => ({
|
|
15363
15760
|
obligationKey,
|
|
15364
15761
|
loanToken: item.loanToken.toLowerCase(),
|
|
15365
15762
|
maturity: item.maturity,
|
|
15366
15763
|
rcfThreshold: item.rcfThreshold.toString()
|
|
15367
15764
|
}));
|
|
15368
|
-
|
|
15765
|
+
let obligationsInserted = 0;
|
|
15766
|
+
for (const batch of batch$1(obligationRows, DEFAULT_BATCH_SIZE$1)) {
|
|
15767
|
+
const inserted = await dbTx.insert(obligations).values(batch).onConflictDoNothing().returning();
|
|
15768
|
+
obligationsInserted += inserted.length;
|
|
15769
|
+
}
|
|
15369
15770
|
const obligationIdKeyRows = Array.from(obligationIdKeysById.entries()).map(([obligationId, input]) => ({
|
|
15370
15771
|
obligationId,
|
|
15371
15772
|
obligationKey: key(input.obligation).toLowerCase(),
|
|
15372
15773
|
chainId: input.chainId,
|
|
15373
15774
|
morphoV2: input.morphoV2.toLowerCase()
|
|
15374
15775
|
}));
|
|
15375
|
-
|
|
15776
|
+
let obligationIdKeysInserted = 0;
|
|
15777
|
+
for (const batch of batch$1(obligationIdKeyRows, DEFAULT_BATCH_SIZE$1)) {
|
|
15778
|
+
const inserted = await dbTx.insert(obligationIdKeys).values(batch).onConflictDoNothing().returning();
|
|
15779
|
+
obligationIdKeysInserted += inserted.length;
|
|
15780
|
+
}
|
|
15376
15781
|
const collateralRows = Array.from(obligationsByKey.entries()).flatMap(([obligationKey, item]) => {
|
|
15377
15782
|
return [...item.collaterals].sort((a, b) => a.asset.toLowerCase().localeCompare(b.asset.toLowerCase())).map((collateral, collateralIndex) => ({
|
|
15378
15783
|
obligationKey,
|
|
15379
15784
|
asset: collateral.asset.toLowerCase(),
|
|
15380
15785
|
oracleAddress: collateral.oracle.toLowerCase(),
|
|
15381
15786
|
lltv: collateral.lltv,
|
|
15382
|
-
maxLif: collateral.maxLif
|
|
15787
|
+
maxLif: collateral.maxLif,
|
|
15383
15788
|
collateralIndex
|
|
15384
15789
|
}));
|
|
15385
15790
|
});
|
|
15386
|
-
|
|
15791
|
+
let obligationCollateralsInserted = 0;
|
|
15792
|
+
for (const batch of batch$1(collateralRows, DEFAULT_BATCH_SIZE$1)) {
|
|
15793
|
+
const inserted = await dbTx.insert(obligationCollateralsV2).values(batch).onConflictDoNothing().returning();
|
|
15794
|
+
obligationCollateralsInserted += inserted.length;
|
|
15795
|
+
}
|
|
15796
|
+
return {
|
|
15797
|
+
obligationsInserted,
|
|
15798
|
+
obligationIdKeysInserted,
|
|
15799
|
+
obligationCollateralsInserted
|
|
15800
|
+
};
|
|
15387
15801
|
});
|
|
15388
15802
|
} catch (err) {
|
|
15389
15803
|
const error = err instanceof Error ? err : new Error(String(err));
|
|
@@ -15433,25 +15847,30 @@ function create$4(db) {
|
|
|
15433
15847
|
}));
|
|
15434
15848
|
},
|
|
15435
15849
|
upsert: async (oracles) => {
|
|
15436
|
-
if (oracles.length === 0) return;
|
|
15850
|
+
if (oracles.length === 0) return 0;
|
|
15437
15851
|
const rows = oracles.map((o) => ({
|
|
15438
15852
|
chainId: o.chainId,
|
|
15439
15853
|
address: o.address.toLowerCase(),
|
|
15440
15854
|
price: o.price !== null ? o.price.toString() : null,
|
|
15441
15855
|
blockNumber: o.blockNumber
|
|
15442
15856
|
}));
|
|
15443
|
-
await db.transaction(async (dbTx) => {
|
|
15444
|
-
|
|
15445
|
-
|
|
15446
|
-
|
|
15447
|
-
|
|
15448
|
-
|
|
15857
|
+
return await db.transaction(async (dbTx) => {
|
|
15858
|
+
let upsertedCount = 0;
|
|
15859
|
+
for (const batch of batch$1(rows, DEFAULT_BATCH_SIZE$1)) {
|
|
15860
|
+
const upserted = await dbTx.insert(oracles$1).values(batch).onConflictDoUpdate({
|
|
15861
|
+
target: [oracles$1.chainId, oracles$1.address],
|
|
15862
|
+
set: {
|
|
15863
|
+
price: sql`COALESCE(EXCLUDED.price, ${oracles$1.price})`,
|
|
15864
|
+
blockNumber: sql`CASE
|
|
15449
15865
|
WHEN EXCLUDED.price IS NULL THEN ${oracles$1.blockNumber}
|
|
15450
15866
|
ELSE EXCLUDED.block_number
|
|
15451
15867
|
END`,
|
|
15452
|
-
|
|
15453
|
-
|
|
15454
|
-
|
|
15868
|
+
updatedAt: sql`NOW()`
|
|
15869
|
+
}
|
|
15870
|
+
}).returning();
|
|
15871
|
+
upsertedCount += upserted.length;
|
|
15872
|
+
}
|
|
15873
|
+
return upsertedCount;
|
|
15455
15874
|
});
|
|
15456
15875
|
}
|
|
15457
15876
|
};
|
|
@@ -15590,8 +16009,8 @@ const create$3 = (db) => {
|
|
|
15590
16009
|
l.obligation_id,
|
|
15591
16010
|
SUM(
|
|
15592
16011
|
CASE
|
|
15593
|
-
WHEN offer_agg.
|
|
15594
|
-
THEN COALESCE(g.consumed::numeric, 0) * (l.upper::numeric - l.lower::numeric) / offer_agg.
|
|
16012
|
+
WHEN offer_agg.max_units > 0
|
|
16013
|
+
THEN COALESCE(g.consumed::numeric, 0) * (l.upper::numeric - l.lower::numeric) / offer_agg.max_units
|
|
15595
16014
|
ELSE 0
|
|
15596
16015
|
END
|
|
15597
16016
|
) AS consumed
|
|
@@ -15606,7 +16025,7 @@ const create$3 = (db) => {
|
|
|
15606
16025
|
group_maker,
|
|
15607
16026
|
"group_group",
|
|
15608
16027
|
obligation_id,
|
|
15609
|
-
MAX(
|
|
16028
|
+
MAX(max_units::numeric) AS max_units
|
|
15610
16029
|
FROM ${offers}
|
|
15611
16030
|
GROUP BY group_chain_id, group_maker, "group_group", obligation_id
|
|
15612
16031
|
) offer_agg
|
|
@@ -16308,7 +16727,7 @@ async function postMigrate(driver) {
|
|
|
16308
16727
|
WHERE o.group_chain_id = t.chain_id
|
|
16309
16728
|
AND o.group_maker = t.maker
|
|
16310
16729
|
AND o.group_group = t."group"
|
|
16311
|
-
AND o.
|
|
16730
|
+
AND o.max_units <= t.consumed;
|
|
16312
16731
|
RETURN NULL;
|
|
16313
16732
|
END;
|
|
16314
16733
|
$$;
|
|
@@ -16337,7 +16756,7 @@ async function postMigrate(driver) {
|
|
|
16337
16756
|
AND g.chain_id = t.group_chain_id
|
|
16338
16757
|
AND g.maker = t.group_maker
|
|
16339
16758
|
AND g."group" = t."group"
|
|
16340
|
-
AND o.
|
|
16759
|
+
AND o.max_units <= g.consumed;
|
|
16341
16760
|
RETURN NULL;
|
|
16342
16761
|
END;
|
|
16343
16762
|
$$;`);
|
|
@@ -16812,16 +17231,16 @@ const maxCollaterals = ({ max }) => single("max_collaterals", `Validates that an
|
|
|
16812
17231
|
if (offer.collaterals.length > max) return { message: `Offer has ${offer.collaterals.length} collaterals, exceeding the maximum of ${max}` };
|
|
16813
17232
|
});
|
|
16814
17233
|
/**
|
|
16815
|
-
* A validation rule that checks if the offer's
|
|
17234
|
+
* A validation rule that checks if the offer's maxUnits is non-zero.
|
|
16816
17235
|
* The contract requires a positive amount; this rule rejects early.
|
|
16817
17236
|
* @returns The issue that was found. If the offer is valid, this will be undefined.
|
|
16818
17237
|
*/
|
|
16819
|
-
const amountNonZero = () => single("amount_non_zero", "Validates that
|
|
16820
|
-
if (offer.
|
|
17238
|
+
const amountNonZero = () => single("amount_non_zero", "Validates that maxUnits is non-zero", (offer) => {
|
|
17239
|
+
if (offer.maxUnits === 0n) return { message: "maxUnits must be non-zero" };
|
|
16821
17240
|
});
|
|
16822
17241
|
/**
|
|
16823
17242
|
* A batch validation rule that ensures all offers within the same group are consistent.
|
|
16824
|
-
* All offers sharing the same group must have the same loan token,
|
|
17243
|
+
* All offers sharing the same group must have the same loan token, maxUnits,
|
|
16825
17244
|
* and side (buy/sell). The contract tracks consumed per group and requires these to match.
|
|
16826
17245
|
*/
|
|
16827
17246
|
const groupConsistency = () => batch("group_consistency", "Validates that all offers in a group have the same loan token, obligation amounts, and side", (offers) => {
|
|
@@ -16838,13 +17257,13 @@ const groupConsistency = () => batch("group_consistency", "Validates that all of
|
|
|
16838
17257
|
if (indices.length <= 1) continue;
|
|
16839
17258
|
const reference = offers[indices[0]];
|
|
16840
17259
|
const refLoanToken = reference.loanToken.toLowerCase();
|
|
16841
|
-
const refUnits = reference.
|
|
17260
|
+
const refUnits = reference.maxUnits;
|
|
16842
17261
|
const refBuy = reference.buy;
|
|
16843
17262
|
for (let j = 1; j < indices.length; j++) {
|
|
16844
17263
|
const idx = indices[j];
|
|
16845
17264
|
const offer = offers[idx];
|
|
16846
17265
|
if (offer.loanToken.toLowerCase() !== refLoanToken) issues.set(idx, { message: `All offers in a group must have the same loan token. Expected ${reference.loanToken}, got ${offer.loanToken}` });
|
|
16847
|
-
else if (offer.
|
|
17266
|
+
else if (offer.maxUnits !== refUnits) issues.set(idx, { message: `All offers in a group must have the same maxUnits. Expected ${refUnits}, got ${offer.maxUnits}` });
|
|
16848
17267
|
else if (offer.buy !== refBuy) issues.set(idx, { message: `All offers in a group must be on the same side. Expected ${refBuy ? "buy" : "sell"}, got ${offer.buy ? "buy" : "sell"}` });
|
|
16849
17268
|
}
|
|
16850
17269
|
}
|