@morpho-dev/router 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +1896 -784
- package/dist/drizzle/migrations/0027_debt-to-transfers.sql +239 -0
- package/dist/drizzle/migrations/0028_obligation_id_and_keys.sql +247 -0
- package/dist/drizzle/migrations/0029_collateral-positions.sql +248 -0
- package/dist/drizzle/migrations/0030_remove_chain_id_from_offer.sql +37 -0
- package/dist/drizzle/migrations/meta/0027_snapshot.json +1581 -0
- package/dist/drizzle/migrations/meta/0028_snapshot.json +1632 -0
- package/dist/drizzle/migrations/meta/0029_snapshot.json +1619 -0
- package/dist/drizzle/migrations/meta/0030_snapshot.json +1652 -0
- package/dist/drizzle/migrations/meta/_journal.json +28 -0
- package/dist/index.browser.d.mts +464 -279
- package/dist/index.browser.d.mts.map +1 -1
- package/dist/index.browser.d.ts +460 -275
- package/dist/index.browser.d.ts.map +1 -1
- package/dist/index.browser.js +3965 -3845
- package/dist/index.browser.js.map +1 -1
- package/dist/index.browser.mjs +3964 -3850
- package/dist/index.browser.mjs.map +1 -1
- package/dist/index.node.d.mts +920 -409
- package/dist/index.node.d.mts.map +1 -1
- package/dist/index.node.d.ts +920 -409
- package/dist/index.node.d.ts.map +1 -1
- package/dist/index.node.js +1952 -1019
- package/dist/index.node.js.map +1 -1
- package/dist/index.node.mjs +1949 -1022
- package/dist/index.node.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.node.js
CHANGED
|
@@ -844,7 +844,7 @@ const reconcile = async (parameters) => {
|
|
|
844
844
|
//#region src/indexer/collectors/Collector.ts
|
|
845
845
|
const names = [
|
|
846
846
|
"offers",
|
|
847
|
-
"
|
|
847
|
+
"morpho_v2",
|
|
848
848
|
"positions",
|
|
849
849
|
"prices"
|
|
850
850
|
];
|
|
@@ -1221,7 +1221,7 @@ var Chain_exports = /* @__PURE__ */ __exportAll({
|
|
|
1221
1221
|
MissingBlockNumberError: () => MissingBlockNumberError,
|
|
1222
1222
|
chainIds: () => chainIds,
|
|
1223
1223
|
chainNames: () => chainNames,
|
|
1224
|
-
chains: () => chains$
|
|
1224
|
+
chains: () => chains$1,
|
|
1225
1225
|
getChain: () => getChain,
|
|
1226
1226
|
getWhitelistedChains: () => getWhitelistedChains,
|
|
1227
1227
|
streamLogs: () => streamLogs
|
|
@@ -1238,17 +1238,17 @@ const chainNameLookup = new Map(Object.entries(ChainId).map(([key, value]) => [v
|
|
|
1238
1238
|
function getChain(chainId) {
|
|
1239
1239
|
const chainName = chainNameLookup.get(chainId);
|
|
1240
1240
|
if (!chainName) return void 0;
|
|
1241
|
-
return chains$
|
|
1241
|
+
return chains$1[chainName];
|
|
1242
1242
|
}
|
|
1243
1243
|
const getWhitelistedChains = () => {
|
|
1244
1244
|
return [
|
|
1245
|
-
chains$
|
|
1246
|
-
chains$
|
|
1247
|
-
chains$
|
|
1248
|
-
chains$
|
|
1245
|
+
chains$1.ethereum,
|
|
1246
|
+
chains$1.base,
|
|
1247
|
+
chains$1["ethereum-virtual-testnet"],
|
|
1248
|
+
chains$1.anvil
|
|
1249
1249
|
];
|
|
1250
1250
|
};
|
|
1251
|
-
const chains$
|
|
1251
|
+
const chains$1 = {
|
|
1252
1252
|
ethereum: {
|
|
1253
1253
|
...viem_chains.mainnet,
|
|
1254
1254
|
id: ChainId.ETHEREUM,
|
|
@@ -1285,16 +1285,16 @@ const chains$2 = {
|
|
|
1285
1285
|
name: "base",
|
|
1286
1286
|
custom: {
|
|
1287
1287
|
morpho: {
|
|
1288
|
-
address: "
|
|
1289
|
-
blockCreated:
|
|
1288
|
+
address: "0x3F067BC9D8898F6ec02D6480c3fF1026E512BcBF",
|
|
1289
|
+
blockCreated: 41799989
|
|
1290
1290
|
},
|
|
1291
1291
|
morphoBlue: {
|
|
1292
1292
|
address: "0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb",
|
|
1293
1293
|
blockCreated: 0
|
|
1294
1294
|
},
|
|
1295
1295
|
mempool: {
|
|
1296
|
-
address: "
|
|
1297
|
-
blockCreated:
|
|
1296
|
+
address: "0xd25c7512EA5035bef4F18c708C0862E1B6151765",
|
|
1297
|
+
blockCreated: 41800226
|
|
1298
1298
|
},
|
|
1299
1299
|
vaults: { factories: {
|
|
1300
1300
|
v1_0: {
|
|
@@ -1618,9 +1618,24 @@ const LLTVSchema = zod.bigint({ coerce: true }).refine((lltv) => {
|
|
|
1618
1618
|
var Collateral_exports = /* @__PURE__ */ __exportAll({
|
|
1619
1619
|
CollateralSchema: () => CollateralSchema,
|
|
1620
1620
|
CollateralsSchema: () => CollateralsSchema,
|
|
1621
|
+
abi: () => abi$1,
|
|
1621
1622
|
from: () => from$17,
|
|
1622
1623
|
random: () => random$3
|
|
1623
1624
|
});
|
|
1625
|
+
const abi$1 = [
|
|
1626
|
+
{
|
|
1627
|
+
type: "address",
|
|
1628
|
+
name: "token"
|
|
1629
|
+
},
|
|
1630
|
+
{
|
|
1631
|
+
type: "uint256",
|
|
1632
|
+
name: "lltv"
|
|
1633
|
+
},
|
|
1634
|
+
{
|
|
1635
|
+
type: "address",
|
|
1636
|
+
name: "oracle"
|
|
1637
|
+
}
|
|
1638
|
+
];
|
|
1624
1639
|
const CollateralSchema = zod.object({
|
|
1625
1640
|
asset: zod.string().transform(transformAddress),
|
|
1626
1641
|
oracle: zod.string().transform(transformAddress),
|
|
@@ -1725,80 +1740,6 @@ var DenominatorIsZeroError = class extends BaseError {
|
|
|
1725
1740
|
}
|
|
1726
1741
|
};
|
|
1727
1742
|
|
|
1728
|
-
//#endregion
|
|
1729
|
-
//#region src/core/Liquidity.ts
|
|
1730
|
-
var Liquidity_exports = /* @__PURE__ */ __exportAll({
|
|
1731
|
-
calculateMaxDebt: () => calculateMaxDebt,
|
|
1732
|
-
generateAllowancePoolId: () => generateAllowancePoolId,
|
|
1733
|
-
generateBalancePoolId: () => generateBalancePoolId,
|
|
1734
|
-
generateDebtPoolId: () => generateDebtPoolId,
|
|
1735
|
-
generateMarketLiquidityPoolId: () => generateMarketLiquidityPoolId,
|
|
1736
|
-
generateObligationCollateralPoolId: () => generateObligationCollateralPoolId,
|
|
1737
|
-
generateUserVaultPositionPoolId: () => generateUserVaultPositionPoolId,
|
|
1738
|
-
generateVaultPositionPoolId: () => generateVaultPositionPoolId
|
|
1739
|
-
});
|
|
1740
|
-
/**
|
|
1741
|
-
* Calculate maximum debt capacity from collateral amount.
|
|
1742
|
-
* @param amount - Collateral amount
|
|
1743
|
-
* @param oraclePrice - Oracle price (scaled to 36 decimals)
|
|
1744
|
-
* @param lltv - Loan-to-value ratio (scaled to 18 decimals)
|
|
1745
|
-
* @returns Maximum debt capacity
|
|
1746
|
-
*/
|
|
1747
|
-
function calculateMaxDebt(amount, oraclePrice, lltv) {
|
|
1748
|
-
return amount * oraclePrice / 10n ** 36n * lltv / 10n ** 18n;
|
|
1749
|
-
}
|
|
1750
|
-
/**
|
|
1751
|
-
* Generate pool ID for balance pools.
|
|
1752
|
-
*/
|
|
1753
|
-
function generateBalancePoolId(parameters) {
|
|
1754
|
-
const { user, chainId, token } = parameters;
|
|
1755
|
-
return `${user}-${chainId.toString()}-${token}-balance`.toLowerCase();
|
|
1756
|
-
}
|
|
1757
|
-
/**
|
|
1758
|
-
* Generate pool ID for allowance pools.
|
|
1759
|
-
*/
|
|
1760
|
-
function generateAllowancePoolId(parameters) {
|
|
1761
|
-
const { user, chainId, token } = parameters;
|
|
1762
|
-
return `${user}-${chainId.toString()}-${token}-allowance`.toLowerCase();
|
|
1763
|
-
}
|
|
1764
|
-
/**
|
|
1765
|
-
* Generate pool ID for obligation collateral pools.
|
|
1766
|
-
* Obligation collateral pools represent collateral already deposited in the obligation.
|
|
1767
|
-
* These pools are shared across all offers with the same obligation.
|
|
1768
|
-
*/
|
|
1769
|
-
function generateObligationCollateralPoolId(parameters) {
|
|
1770
|
-
const { user, chainId, obligationId, token } = parameters;
|
|
1771
|
-
return `${user}-${chainId.toString()}-${obligationId}-${token}-obligation-collateral`.toLowerCase();
|
|
1772
|
-
}
|
|
1773
|
-
/**
|
|
1774
|
-
* Generate pool ID for debt pools.
|
|
1775
|
-
*/
|
|
1776
|
-
function generateDebtPoolId(parameters) {
|
|
1777
|
-
const { user, chainId, obligationId } = parameters;
|
|
1778
|
-
return `${user}-${chainId.toString()}-${obligationId}-debt`.toLowerCase();
|
|
1779
|
-
}
|
|
1780
|
-
/**
|
|
1781
|
-
* Generate pool ID for user position in a vault.
|
|
1782
|
-
*/
|
|
1783
|
-
function generateUserVaultPositionPoolId(parameters) {
|
|
1784
|
-
const { user, chainId, vault } = parameters;
|
|
1785
|
-
return `${user}-${chainId.toString()}-${vault}-user-vault-position`.toLowerCase();
|
|
1786
|
-
}
|
|
1787
|
-
/**
|
|
1788
|
-
* Generate pool ID for vault position in a market.
|
|
1789
|
-
*/
|
|
1790
|
-
function generateVaultPositionPoolId(parameters) {
|
|
1791
|
-
const { vault, chainId, marketId } = parameters;
|
|
1792
|
-
return `${vault}-${chainId.toString()}-${marketId}-vault-position`.toLowerCase();
|
|
1793
|
-
}
|
|
1794
|
-
/**
|
|
1795
|
-
* Generate pool ID for market total liquidity.
|
|
1796
|
-
*/
|
|
1797
|
-
function generateMarketLiquidityPoolId(parameters) {
|
|
1798
|
-
const { chainId, marketId } = parameters;
|
|
1799
|
-
return `${chainId.toString()}-${marketId}-market-liquidity`.toLowerCase();
|
|
1800
|
-
}
|
|
1801
|
-
|
|
1802
1743
|
//#endregion
|
|
1803
1744
|
//#region src/core/Maturity.ts
|
|
1804
1745
|
var Maturity_exports = /* @__PURE__ */ __exportAll({
|
|
@@ -1931,18 +1872,38 @@ var Obligation_exports = /* @__PURE__ */ __exportAll({
|
|
|
1931
1872
|
CollateralsAreNotSortedError: () => CollateralsAreNotSortedError,
|
|
1932
1873
|
InvalidObligationError: () => InvalidObligationError,
|
|
1933
1874
|
ObligationSchema: () => ObligationSchema,
|
|
1875
|
+
abi: () => abi,
|
|
1934
1876
|
from: () => from$15,
|
|
1935
1877
|
fromOffer: () => fromOffer$1,
|
|
1936
1878
|
fromSnakeCase: () => fromSnakeCase$2,
|
|
1937
|
-
|
|
1938
|
-
random: () => random$2
|
|
1879
|
+
key: () => key,
|
|
1880
|
+
random: () => random$2,
|
|
1881
|
+
tupleAbi: () => tupleAbi
|
|
1939
1882
|
});
|
|
1940
1883
|
const ObligationSchema = zod.object({
|
|
1941
|
-
chainId: zod.number().min(0).max(Number.MAX_SAFE_INTEGER),
|
|
1942
1884
|
loanToken: zod.string().transform(transformAddress),
|
|
1943
1885
|
collaterals: CollateralsSchema,
|
|
1944
1886
|
maturity: MaturitySchema
|
|
1945
1887
|
});
|
|
1888
|
+
const abi = [
|
|
1889
|
+
{
|
|
1890
|
+
type: "address",
|
|
1891
|
+
name: "loanToken"
|
|
1892
|
+
},
|
|
1893
|
+
{
|
|
1894
|
+
type: "tuple[]",
|
|
1895
|
+
name: "collaterals",
|
|
1896
|
+
components: abi$1
|
|
1897
|
+
},
|
|
1898
|
+
{
|
|
1899
|
+
type: "uint256",
|
|
1900
|
+
name: "maturity"
|
|
1901
|
+
}
|
|
1902
|
+
];
|
|
1903
|
+
const tupleAbi = [{
|
|
1904
|
+
type: "tuple",
|
|
1905
|
+
components: abi
|
|
1906
|
+
}];
|
|
1946
1907
|
/**
|
|
1947
1908
|
* Creates an obligation from the given parameters.
|
|
1948
1909
|
* @constructor
|
|
@@ -1953,7 +1914,6 @@ const ObligationSchema = zod.object({
|
|
|
1953
1914
|
* @example
|
|
1954
1915
|
* ```ts
|
|
1955
1916
|
* const obligation = Obligation.from({
|
|
1956
|
-
* chainId: 1,
|
|
1957
1917
|
* loanToken: privateKeyToAccount(generatePrivateKey()).address,
|
|
1958
1918
|
* collaterals: [
|
|
1959
1919
|
* Collateral.from({
|
|
@@ -1973,7 +1933,6 @@ function from$15(parameters) {
|
|
|
1973
1933
|
maturity: from$16(parameters.maturity)
|
|
1974
1934
|
});
|
|
1975
1935
|
return {
|
|
1976
|
-
chainId: parsedObligation.chainId,
|
|
1977
1936
|
loanToken: parsedObligation.loanToken.toLowerCase(),
|
|
1978
1937
|
collaterals: parsedObligation.collaterals.sort((a, b) => a.asset.localeCompare(b.asset)),
|
|
1979
1938
|
maturity: parsedObligation.maturity
|
|
@@ -1992,49 +1951,27 @@ function fromSnakeCase$2(input) {
|
|
|
1992
1951
|
return from$15(fromSnakeCase$3(input));
|
|
1993
1952
|
}
|
|
1994
1953
|
/**
|
|
1995
|
-
* Calculates
|
|
1996
|
-
* The
|
|
1954
|
+
* Calculates a canonical key for an obligation payload.
|
|
1955
|
+
* The key is computed as keccak256(abi.encode(loanToken, collaterals, maturity)).
|
|
1997
1956
|
* @throws If the collaterals are not sorted alphabetically by address. {@link CollateralsAreNotSortedError}
|
|
1998
|
-
* @param parameters - {@link
|
|
1999
|
-
* @returns The obligation
|
|
1957
|
+
* @param parameters - {@link key.Parameters}
|
|
1958
|
+
* @returns The obligation key as a 32-byte hex string. {@link key.ReturnType}
|
|
2000
1959
|
*
|
|
2001
1960
|
* @example
|
|
2002
1961
|
* ```ts
|
|
2003
1962
|
* const obligation = Obligation.random();
|
|
2004
|
-
* const
|
|
2005
|
-
* console.log(
|
|
1963
|
+
* const key = Obligation.key(obligation);
|
|
1964
|
+
* console.log(key); // 0x1234567890123456789012345678901234567890123456789012345678901234
|
|
2006
1965
|
* ```
|
|
2007
1966
|
*/
|
|
2008
|
-
function
|
|
1967
|
+
function key(parameters) {
|
|
2009
1968
|
let lastAsset = "";
|
|
2010
1969
|
for (const collateral of parameters.collaterals) {
|
|
2011
1970
|
const newAsset = collateral.asset.toLowerCase();
|
|
2012
1971
|
if (newAsset.localeCompare(lastAsset) < 0) throw new CollateralsAreNotSortedError();
|
|
2013
1972
|
lastAsset = newAsset;
|
|
2014
1973
|
}
|
|
2015
|
-
return (0, viem.keccak256)((0, viem.encodeAbiParameters)([
|
|
2016
|
-
{ type: "uint256" },
|
|
2017
|
-
{ type: "address" },
|
|
2018
|
-
{
|
|
2019
|
-
type: "tuple[]",
|
|
2020
|
-
components: [
|
|
2021
|
-
{
|
|
2022
|
-
type: "address",
|
|
2023
|
-
name: "token"
|
|
2024
|
-
},
|
|
2025
|
-
{
|
|
2026
|
-
type: "uint256",
|
|
2027
|
-
name: "lltv"
|
|
2028
|
-
},
|
|
2029
|
-
{
|
|
2030
|
-
type: "address",
|
|
2031
|
-
name: "oracle"
|
|
2032
|
-
}
|
|
2033
|
-
]
|
|
2034
|
-
},
|
|
2035
|
-
{ type: "uint256" }
|
|
2036
|
-
], [
|
|
2037
|
-
BigInt(parameters.chainId),
|
|
1974
|
+
return (0, viem.keccak256)((0, viem.encodeAbiParameters)(abi, [
|
|
2038
1975
|
parameters.loanToken.toLowerCase(),
|
|
2039
1976
|
parameters.collaterals.map((c) => ({
|
|
2040
1977
|
token: c.asset.toLowerCase(),
|
|
@@ -2055,7 +1992,6 @@ function id(parameters) {
|
|
|
2055
1992
|
*/
|
|
2056
1993
|
function random$2() {
|
|
2057
1994
|
return from$15({
|
|
2058
|
-
chainId: 1,
|
|
2059
1995
|
loanToken: address(),
|
|
2060
1996
|
collaterals: [random$3()],
|
|
2061
1997
|
maturity: from$16("end_of_next_quarter")
|
|
@@ -2070,7 +2006,6 @@ function random$2() {
|
|
|
2070
2006
|
*/
|
|
2071
2007
|
function fromOffer$1(offer) {
|
|
2072
2008
|
return from$15({
|
|
2073
|
-
chainId: offer.chainId,
|
|
2074
2009
|
loanToken: offer.loanToken,
|
|
2075
2010
|
collaterals: offer.collaterals,
|
|
2076
2011
|
maturity: offer.maturity
|
|
@@ -2089,6 +2024,121 @@ var CollateralsAreNotSortedError = class extends BaseError {
|
|
|
2089
2024
|
}
|
|
2090
2025
|
};
|
|
2091
2026
|
|
|
2027
|
+
//#endregion
|
|
2028
|
+
//#region src/core/Id.ts
|
|
2029
|
+
var Id_exports = /* @__PURE__ */ __exportAll({
|
|
2030
|
+
creationCode: () => creationCode,
|
|
2031
|
+
toId: () => toId
|
|
2032
|
+
});
|
|
2033
|
+
const CREATION_CODE_PREFIX = "0x603f380380603f5f395ff3";
|
|
2034
|
+
/**
|
|
2035
|
+
* Builds the same creation code as `IdLib.creationCode` in Solidity.
|
|
2036
|
+
*
|
|
2037
|
+
* Layout: `prefix (11 bytes) + chainId (32 bytes) + morphoV2 (20 bytes) + abi.encode(obligation)`.
|
|
2038
|
+
*
|
|
2039
|
+
* @param parameters - {@link creationCode.Parameters}
|
|
2040
|
+
* @returns The CREATE2 init code bytes. {@link creationCode.ReturnType}
|
|
2041
|
+
*/
|
|
2042
|
+
function creationCode(parameters) {
|
|
2043
|
+
const encodedObligation = (0, viem.encodeAbiParameters)(tupleAbi, [{
|
|
2044
|
+
loanToken: parameters.obligation.loanToken.toLowerCase(),
|
|
2045
|
+
collaterals: parameters.obligation.collaterals.map((collateral) => ({
|
|
2046
|
+
token: collateral.asset.toLowerCase(),
|
|
2047
|
+
lltv: collateral.lltv,
|
|
2048
|
+
oracle: collateral.oracle.toLowerCase()
|
|
2049
|
+
})),
|
|
2050
|
+
maturity: BigInt(parameters.obligation.maturity)
|
|
2051
|
+
}]);
|
|
2052
|
+
return (0, viem.concatHex)([
|
|
2053
|
+
CREATION_CODE_PREFIX,
|
|
2054
|
+
(0, viem.numberToHex)(BigInt(parameters.chainId), { size: 32 }),
|
|
2055
|
+
parameters.morphoV2.toLowerCase(),
|
|
2056
|
+
encodedObligation
|
|
2057
|
+
]);
|
|
2058
|
+
}
|
|
2059
|
+
/**
|
|
2060
|
+
* Computes the same id as `IdLib.toId` in Solidity.
|
|
2061
|
+
* @param parameters - {@link toId.Parameters}
|
|
2062
|
+
* @returns The obligation id. {@link toId.ReturnType}
|
|
2063
|
+
*/
|
|
2064
|
+
function toId(parameters) {
|
|
2065
|
+
return (0, viem.keccak256)(creationCode(parameters));
|
|
2066
|
+
}
|
|
2067
|
+
|
|
2068
|
+
//#endregion
|
|
2069
|
+
//#region src/core/Liquidity.ts
|
|
2070
|
+
var Liquidity_exports = /* @__PURE__ */ __exportAll({
|
|
2071
|
+
calculateMaxDebt: () => calculateMaxDebt,
|
|
2072
|
+
generateAllowancePoolId: () => generateAllowancePoolId,
|
|
2073
|
+
generateBalancePoolId: () => generateBalancePoolId,
|
|
2074
|
+
generateDebtPoolId: () => generateDebtPoolId,
|
|
2075
|
+
generateMarketLiquidityPoolId: () => generateMarketLiquidityPoolId,
|
|
2076
|
+
generateObligationCollateralPoolId: () => generateObligationCollateralPoolId,
|
|
2077
|
+
generateUserVaultPositionPoolId: () => generateUserVaultPositionPoolId,
|
|
2078
|
+
generateVaultPositionPoolId: () => generateVaultPositionPoolId
|
|
2079
|
+
});
|
|
2080
|
+
/**
|
|
2081
|
+
* Calculate maximum debt capacity from collateral amount.
|
|
2082
|
+
* @param amount - Collateral amount
|
|
2083
|
+
* @param oraclePrice - Oracle price (scaled to 36 decimals)
|
|
2084
|
+
* @param lltv - Loan-to-value ratio (scaled to 18 decimals)
|
|
2085
|
+
* @returns Maximum debt capacity
|
|
2086
|
+
*/
|
|
2087
|
+
function calculateMaxDebt(amount, oraclePrice, lltv) {
|
|
2088
|
+
return amount * oraclePrice / 10n ** 36n * lltv / 10n ** 18n;
|
|
2089
|
+
}
|
|
2090
|
+
/**
|
|
2091
|
+
* Generate pool ID for balance pools.
|
|
2092
|
+
*/
|
|
2093
|
+
function generateBalancePoolId(parameters) {
|
|
2094
|
+
const { user, chainId, token } = parameters;
|
|
2095
|
+
return `${user}-${chainId.toString()}-${token}-balance`.toLowerCase();
|
|
2096
|
+
}
|
|
2097
|
+
/**
|
|
2098
|
+
* Generate pool ID for allowance pools.
|
|
2099
|
+
*/
|
|
2100
|
+
function generateAllowancePoolId(parameters) {
|
|
2101
|
+
const { user, chainId, token } = parameters;
|
|
2102
|
+
return `${user}-${chainId.toString()}-${token}-allowance`.toLowerCase();
|
|
2103
|
+
}
|
|
2104
|
+
/**
|
|
2105
|
+
* Generate pool ID for obligation collateral pools.
|
|
2106
|
+
* Obligation collateral pools represent collateral already deposited in the obligation.
|
|
2107
|
+
* These pools are shared across all offers with the same obligation.
|
|
2108
|
+
*/
|
|
2109
|
+
function generateObligationCollateralPoolId(parameters) {
|
|
2110
|
+
const { user, chainId, obligationId, token } = parameters;
|
|
2111
|
+
return `${user}-${chainId.toString()}-${obligationId}-${token}-obligation-collateral`.toLowerCase();
|
|
2112
|
+
}
|
|
2113
|
+
/**
|
|
2114
|
+
* Generate pool ID for debt pools.
|
|
2115
|
+
*/
|
|
2116
|
+
function generateDebtPoolId(parameters) {
|
|
2117
|
+
const { user, chainId, obligationId } = parameters;
|
|
2118
|
+
return `${user}-${chainId.toString()}-${obligationId}-debt`.toLowerCase();
|
|
2119
|
+
}
|
|
2120
|
+
/**
|
|
2121
|
+
* Generate pool ID for user position in a vault.
|
|
2122
|
+
*/
|
|
2123
|
+
function generateUserVaultPositionPoolId(parameters) {
|
|
2124
|
+
const { user, chainId, vault } = parameters;
|
|
2125
|
+
return `${user}-${chainId.toString()}-${vault}-user-vault-position`.toLowerCase();
|
|
2126
|
+
}
|
|
2127
|
+
/**
|
|
2128
|
+
* Generate pool ID for vault position in a market.
|
|
2129
|
+
*/
|
|
2130
|
+
function generateVaultPositionPoolId(parameters) {
|
|
2131
|
+
const { vault, chainId, marketId } = parameters;
|
|
2132
|
+
return `${vault}-${chainId.toString()}-${marketId}-vault-position`.toLowerCase();
|
|
2133
|
+
}
|
|
2134
|
+
/**
|
|
2135
|
+
* Generate pool ID for market total liquidity.
|
|
2136
|
+
*/
|
|
2137
|
+
function generateMarketLiquidityPoolId(parameters) {
|
|
2138
|
+
const { chainId, marketId } = parameters;
|
|
2139
|
+
return `${chainId.toString()}-${marketId}-market-liquidity`.toLowerCase();
|
|
2140
|
+
}
|
|
2141
|
+
|
|
2092
2142
|
//#endregion
|
|
2093
2143
|
//#region src/core/Offer.ts
|
|
2094
2144
|
var Offer_exports = /* @__PURE__ */ __exportAll({
|
|
@@ -2097,17 +2147,19 @@ var Offer_exports = /* @__PURE__ */ __exportAll({
|
|
|
2097
2147
|
Status: () => Status,
|
|
2098
2148
|
consumedEvent: () => consumedEvent,
|
|
2099
2149
|
decode: () => decode$1,
|
|
2100
|
-
domain: () => domain,
|
|
2101
2150
|
encode: () => encode$1,
|
|
2102
2151
|
from: () => from$14,
|
|
2103
2152
|
fromSnakeCase: () => fromSnakeCase$1,
|
|
2104
2153
|
hash: () => hash,
|
|
2154
|
+
liquidateEvent: () => liquidateEvent,
|
|
2105
2155
|
obligationId: () => obligationId,
|
|
2106
2156
|
random: () => random$1,
|
|
2157
|
+
repayEvent: () => repayEvent,
|
|
2107
2158
|
serialize: () => serialize,
|
|
2159
|
+
supplyCollateralEvent: () => supplyCollateralEvent,
|
|
2108
2160
|
takeEvent: () => takeEvent,
|
|
2109
2161
|
toSnakeCase: () => toSnakeCase,
|
|
2110
|
-
|
|
2162
|
+
withdrawCollateralEvent: () => withdrawCollateralEvent
|
|
2111
2163
|
});
|
|
2112
2164
|
/** Internal symbol for caching the computed hash. */
|
|
2113
2165
|
const HASH_CACHE = Symbol("offer.hash");
|
|
@@ -2137,7 +2189,6 @@ const OfferSchema = () => {
|
|
|
2137
2189
|
zod.bigint()
|
|
2138
2190
|
]).optional().default("0x0000000000000000000000000000000000000000000000000000000000000000").transform(transformBytes32),
|
|
2139
2191
|
buy: zod.boolean(),
|
|
2140
|
-
chainId: zod.number().min(0).max(Number.MAX_SAFE_INTEGER),
|
|
2141
2192
|
loanToken: zod.string().transform(transformAddress),
|
|
2142
2193
|
collaterals: CollateralsSchema,
|
|
2143
2194
|
callback: zod.object({
|
|
@@ -2206,7 +2257,6 @@ const serialize = (offer) => ({
|
|
|
2206
2257
|
group: offer.group,
|
|
2207
2258
|
session: offer.session,
|
|
2208
2259
|
buy: offer.buy,
|
|
2209
|
-
chainId: offer.chainId,
|
|
2210
2260
|
loanToken: offer.loanToken,
|
|
2211
2261
|
collaterals: offer.collaterals.map((c) => ({
|
|
2212
2262
|
asset: c.asset,
|
|
@@ -2227,7 +2277,6 @@ const serialize = (offer) => ({
|
|
|
2227
2277
|
* @returns {Offer} A randomly generated Offer object.
|
|
2228
2278
|
*/
|
|
2229
2279
|
function random$1(config) {
|
|
2230
|
-
const chain = config?.chains ? config.chains[int(config.chains.length)] : chains$2.ethereum;
|
|
2231
2280
|
const loanToken = config?.loanTokens ? config.loanTokens[int(config.loanTokens.length)] : address();
|
|
2232
2281
|
const collateralCandidates = config?.collateralTokens ? config.collateralTokens.filter((a) => a !== loanToken) : [address()];
|
|
2233
2282
|
collateralCandidates[int(collateralCandidates.length)];
|
|
@@ -2273,7 +2322,6 @@ function random$1(config) {
|
|
|
2273
2322
|
group: config?.group ?? hex(32),
|
|
2274
2323
|
session: config?.session ?? hex(32),
|
|
2275
2324
|
buy,
|
|
2276
|
-
chainId: chain.id,
|
|
2277
2325
|
loanToken,
|
|
2278
2326
|
collaterals: config?.collaterals ?? Array.from({ length: int(3) + 1 }, () => ({
|
|
2279
2327
|
...random$3(),
|
|
@@ -2293,150 +2341,36 @@ const weightedChoice = (pairs) => {
|
|
|
2293
2341
|
return pairs[0][0];
|
|
2294
2342
|
};
|
|
2295
2343
|
/**
|
|
2296
|
-
*
|
|
2297
|
-
*
|
|
2298
|
-
*
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
chainId: BigInt(chainId),
|
|
2302
|
-
verifyingContract: viem.zeroAddress
|
|
2303
|
-
});
|
|
2304
|
-
/**
|
|
2305
|
-
* The EIP-712 types for the offer.
|
|
2306
|
-
* @warning The ordering of the types should NEVER be changed. The offer hash is computed based on the order of the types.
|
|
2307
|
-
* @returns The EIP-712 types.
|
|
2344
|
+
* Computes the canonical chain-agnostic offer hash.
|
|
2345
|
+
* The hash is `keccak256(abi.encode(offer))` using {@link encode}.
|
|
2346
|
+
*
|
|
2347
|
+
* @param offer - Offer payload to hash.
|
|
2348
|
+
* @returns 32-byte offer hash.
|
|
2308
2349
|
*/
|
|
2309
|
-
const types = {
|
|
2310
|
-
EIP712Domain: [{
|
|
2311
|
-
name: "chainId",
|
|
2312
|
-
type: "uint256"
|
|
2313
|
-
}, {
|
|
2314
|
-
name: "verifyingContract",
|
|
2315
|
-
type: "address"
|
|
2316
|
-
}],
|
|
2317
|
-
Offer: [
|
|
2318
|
-
{
|
|
2319
|
-
name: "maker",
|
|
2320
|
-
type: "address"
|
|
2321
|
-
},
|
|
2322
|
-
{
|
|
2323
|
-
name: "assets",
|
|
2324
|
-
type: "uint256"
|
|
2325
|
-
},
|
|
2326
|
-
{
|
|
2327
|
-
name: "obligationUnits",
|
|
2328
|
-
type: "uint256"
|
|
2329
|
-
},
|
|
2330
|
-
{
|
|
2331
|
-
name: "obligationShares",
|
|
2332
|
-
type: "uint256"
|
|
2333
|
-
},
|
|
2334
|
-
{
|
|
2335
|
-
name: "tick",
|
|
2336
|
-
type: "uint256"
|
|
2337
|
-
},
|
|
2338
|
-
{
|
|
2339
|
-
name: "maturity",
|
|
2340
|
-
type: "uint256"
|
|
2341
|
-
},
|
|
2342
|
-
{
|
|
2343
|
-
name: "expiry",
|
|
2344
|
-
type: "uint256"
|
|
2345
|
-
},
|
|
2346
|
-
{
|
|
2347
|
-
name: "group",
|
|
2348
|
-
type: "bytes32"
|
|
2349
|
-
},
|
|
2350
|
-
{
|
|
2351
|
-
name: "session",
|
|
2352
|
-
type: "bytes32"
|
|
2353
|
-
},
|
|
2354
|
-
{
|
|
2355
|
-
name: "buy",
|
|
2356
|
-
type: "bool"
|
|
2357
|
-
},
|
|
2358
|
-
{
|
|
2359
|
-
name: "loanToken",
|
|
2360
|
-
type: "address"
|
|
2361
|
-
},
|
|
2362
|
-
{
|
|
2363
|
-
name: "collaterals",
|
|
2364
|
-
type: "Collateral[]"
|
|
2365
|
-
},
|
|
2366
|
-
{
|
|
2367
|
-
name: "callback",
|
|
2368
|
-
type: "Callback"
|
|
2369
|
-
},
|
|
2370
|
-
{
|
|
2371
|
-
name: "receiverIfMakerIsSeller",
|
|
2372
|
-
type: "address"
|
|
2373
|
-
}
|
|
2374
|
-
],
|
|
2375
|
-
Collateral: [
|
|
2376
|
-
{
|
|
2377
|
-
name: "asset",
|
|
2378
|
-
type: "address"
|
|
2379
|
-
},
|
|
2380
|
-
{
|
|
2381
|
-
name: "oracle",
|
|
2382
|
-
type: "address"
|
|
2383
|
-
},
|
|
2384
|
-
{
|
|
2385
|
-
name: "lltv",
|
|
2386
|
-
type: "uint256"
|
|
2387
|
-
}
|
|
2388
|
-
],
|
|
2389
|
-
Callback: [{
|
|
2390
|
-
name: "address",
|
|
2391
|
-
type: "address"
|
|
2392
|
-
}, {
|
|
2393
|
-
name: "data",
|
|
2394
|
-
type: "bytes"
|
|
2395
|
-
}]
|
|
2396
|
-
};
|
|
2397
2350
|
function hash(offer) {
|
|
2398
2351
|
const cached = offer[HASH_CACHE];
|
|
2399
2352
|
if (cached) return cached;
|
|
2400
|
-
const computed = (0, viem.
|
|
2401
|
-
domain: domain(offer.chainId),
|
|
2402
|
-
message: {
|
|
2403
|
-
maker: offer.maker.toLowerCase(),
|
|
2404
|
-
assets: offer.assets,
|
|
2405
|
-
obligationUnits: offer.obligationUnits,
|
|
2406
|
-
obligationShares: offer.obligationShares,
|
|
2407
|
-
tick: BigInt(offer.tick),
|
|
2408
|
-
maturity: BigInt(offer.maturity),
|
|
2409
|
-
expiry: BigInt(offer.expiry),
|
|
2410
|
-
group: offer.group,
|
|
2411
|
-
session: offer.session,
|
|
2412
|
-
buy: offer.buy,
|
|
2413
|
-
loanToken: offer.loanToken.toLowerCase(),
|
|
2414
|
-
collaterals: offer.collaterals,
|
|
2415
|
-
callback: {
|
|
2416
|
-
address: offer.callback.address.toLowerCase(),
|
|
2417
|
-
data: offer.callback.data
|
|
2418
|
-
},
|
|
2419
|
-
receiverIfMakerIsSeller: offer.receiverIfMakerIsSeller.toLowerCase()
|
|
2420
|
-
},
|
|
2421
|
-
primaryType: "Offer",
|
|
2422
|
-
types
|
|
2423
|
-
});
|
|
2353
|
+
const computed = (0, viem.keccak256)(encode$1(offer));
|
|
2424
2354
|
offer[HASH_CACHE] = computed;
|
|
2425
2355
|
return computed;
|
|
2426
2356
|
}
|
|
2427
2357
|
/**
|
|
2428
|
-
* Calculates the obligation id for an offer
|
|
2429
|
-
* The id is computed
|
|
2358
|
+
* Calculates the onchain obligation id for an offer.
|
|
2359
|
+
* The id is computed with {@link Id.toId}.
|
|
2430
2360
|
* @param offer - The offer to calculate the obligation id for.
|
|
2361
|
+
* @param parameters - The chain context used by the onchain id function.
|
|
2431
2362
|
* @returns The obligation id as a 32-byte hex string.
|
|
2432
2363
|
*/
|
|
2433
|
-
function obligationId(offer) {
|
|
2434
|
-
return
|
|
2435
|
-
chainId:
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2364
|
+
function obligationId(offer, parameters) {
|
|
2365
|
+
return toId({
|
|
2366
|
+
chainId: parameters.chainId,
|
|
2367
|
+
morphoV2: parameters.morphoV2,
|
|
2368
|
+
obligation: from$15({
|
|
2369
|
+
loanToken: offer.loanToken,
|
|
2370
|
+
collaterals: offer.collaterals,
|
|
2371
|
+
maturity: offer.maturity
|
|
2372
|
+
})
|
|
2373
|
+
});
|
|
2440
2374
|
}
|
|
2441
2375
|
const OfferAbi = [
|
|
2442
2376
|
{
|
|
@@ -2479,10 +2413,6 @@ const OfferAbi = [
|
|
|
2479
2413
|
name: "buy",
|
|
2480
2414
|
type: "bool"
|
|
2481
2415
|
},
|
|
2482
|
-
{
|
|
2483
|
-
name: "chainId",
|
|
2484
|
-
type: "uint256"
|
|
2485
|
-
},
|
|
2486
2416
|
{
|
|
2487
2417
|
name: "loanToken",
|
|
2488
2418
|
type: "address"
|
|
@@ -2537,7 +2467,6 @@ function encode$1(offer) {
|
|
|
2537
2467
|
offer.group,
|
|
2538
2468
|
offer.session,
|
|
2539
2469
|
offer.buy,
|
|
2540
|
-
BigInt(offer.chainId),
|
|
2541
2470
|
offer.loanToken,
|
|
2542
2471
|
BigInt(offer.start),
|
|
2543
2472
|
offer.collaterals,
|
|
@@ -2563,10 +2492,9 @@ function decode$1(data) {
|
|
|
2563
2492
|
group: decoded[7],
|
|
2564
2493
|
session: decoded[8],
|
|
2565
2494
|
buy: decoded[9],
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
collaterals: decoded[13].map((c) => {
|
|
2495
|
+
loanToken: decoded[10],
|
|
2496
|
+
start: Number(decoded[11]),
|
|
2497
|
+
collaterals: decoded[12].map((c) => {
|
|
2570
2498
|
return from$17({
|
|
2571
2499
|
asset: c.asset,
|
|
2572
2500
|
oracle: c.oracle,
|
|
@@ -2574,23 +2502,145 @@ function decode$1(data) {
|
|
|
2574
2502
|
});
|
|
2575
2503
|
}),
|
|
2576
2504
|
callback: {
|
|
2577
|
-
address: decoded[
|
|
2578
|
-
data: decoded[
|
|
2505
|
+
address: decoded[13].address,
|
|
2506
|
+
data: decoded[13].data
|
|
2507
|
+
},
|
|
2508
|
+
receiverIfMakerIsSeller: decoded[14]
|
|
2509
|
+
});
|
|
2510
|
+
}
|
|
2511
|
+
/**
|
|
2512
|
+
* ABI for the Take event emitted by the Morpho V2 contract.
|
|
2513
|
+
*/
|
|
2514
|
+
const takeEvent = {
|
|
2515
|
+
type: "event",
|
|
2516
|
+
name: "Take",
|
|
2517
|
+
inputs: [
|
|
2518
|
+
{
|
|
2519
|
+
name: "caller",
|
|
2520
|
+
type: "address",
|
|
2521
|
+
indexed: false,
|
|
2522
|
+
internalType: "address"
|
|
2523
|
+
},
|
|
2524
|
+
{
|
|
2525
|
+
name: "id",
|
|
2526
|
+
type: "bytes32",
|
|
2527
|
+
indexed: true,
|
|
2528
|
+
internalType: "bytes32"
|
|
2529
|
+
},
|
|
2530
|
+
{
|
|
2531
|
+
name: "maker",
|
|
2532
|
+
type: "address",
|
|
2533
|
+
indexed: true,
|
|
2534
|
+
internalType: "address"
|
|
2535
|
+
},
|
|
2536
|
+
{
|
|
2537
|
+
name: "taker",
|
|
2538
|
+
type: "address",
|
|
2539
|
+
indexed: true,
|
|
2540
|
+
internalType: "address"
|
|
2541
|
+
},
|
|
2542
|
+
{
|
|
2543
|
+
name: "offerIsBuy",
|
|
2544
|
+
type: "bool",
|
|
2545
|
+
indexed: false,
|
|
2546
|
+
internalType: "bool"
|
|
2547
|
+
},
|
|
2548
|
+
{
|
|
2549
|
+
name: "buyerAssets",
|
|
2550
|
+
type: "uint256",
|
|
2551
|
+
indexed: false,
|
|
2552
|
+
internalType: "uint256"
|
|
2553
|
+
},
|
|
2554
|
+
{
|
|
2555
|
+
name: "sellerAssets",
|
|
2556
|
+
type: "uint256",
|
|
2557
|
+
indexed: false,
|
|
2558
|
+
internalType: "uint256"
|
|
2559
|
+
},
|
|
2560
|
+
{
|
|
2561
|
+
name: "obligationUnits",
|
|
2562
|
+
type: "uint256",
|
|
2563
|
+
indexed: false,
|
|
2564
|
+
internalType: "uint256"
|
|
2565
|
+
},
|
|
2566
|
+
{
|
|
2567
|
+
name: "obligationShares",
|
|
2568
|
+
type: "uint256",
|
|
2569
|
+
indexed: false,
|
|
2570
|
+
internalType: "uint256"
|
|
2571
|
+
},
|
|
2572
|
+
{
|
|
2573
|
+
name: "buyerIsLender",
|
|
2574
|
+
type: "bool",
|
|
2575
|
+
indexed: false,
|
|
2576
|
+
internalType: "bool"
|
|
2577
|
+
},
|
|
2578
|
+
{
|
|
2579
|
+
name: "sellerIsBorrower",
|
|
2580
|
+
type: "bool",
|
|
2581
|
+
indexed: false,
|
|
2582
|
+
internalType: "bool"
|
|
2583
|
+
},
|
|
2584
|
+
{
|
|
2585
|
+
name: "sellerReceiver",
|
|
2586
|
+
type: "address",
|
|
2587
|
+
indexed: false,
|
|
2588
|
+
internalType: "address"
|
|
2589
|
+
},
|
|
2590
|
+
{
|
|
2591
|
+
name: "group",
|
|
2592
|
+
type: "bytes32",
|
|
2593
|
+
indexed: false,
|
|
2594
|
+
internalType: "bytes32"
|
|
2595
|
+
},
|
|
2596
|
+
{
|
|
2597
|
+
name: "consumed",
|
|
2598
|
+
type: "uint256",
|
|
2599
|
+
indexed: false,
|
|
2600
|
+
internalType: "uint256"
|
|
2601
|
+
}
|
|
2602
|
+
],
|
|
2603
|
+
anonymous: false
|
|
2604
|
+
};
|
|
2605
|
+
/**
|
|
2606
|
+
* ABI for the Consume event emitted by the Obligation contract.
|
|
2607
|
+
*/
|
|
2608
|
+
const consumedEvent = {
|
|
2609
|
+
type: "event",
|
|
2610
|
+
name: "Consume",
|
|
2611
|
+
inputs: [
|
|
2612
|
+
{
|
|
2613
|
+
name: "user",
|
|
2614
|
+
type: "address",
|
|
2615
|
+
indexed: true,
|
|
2616
|
+
internalType: "address"
|
|
2579
2617
|
},
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2618
|
+
{
|
|
2619
|
+
name: "group",
|
|
2620
|
+
type: "bytes32",
|
|
2621
|
+
indexed: true,
|
|
2622
|
+
internalType: "bytes32"
|
|
2623
|
+
},
|
|
2624
|
+
{
|
|
2625
|
+
name: "amount",
|
|
2626
|
+
type: "uint256",
|
|
2627
|
+
indexed: false,
|
|
2628
|
+
internalType: "uint256"
|
|
2629
|
+
}
|
|
2630
|
+
],
|
|
2631
|
+
anonymous: false
|
|
2632
|
+
};
|
|
2583
2633
|
/**
|
|
2584
|
-
* ABI for the
|
|
2634
|
+
* ABI for the Repay event emitted by the MorphoV2 contract.
|
|
2585
2635
|
*/
|
|
2586
|
-
const
|
|
2636
|
+
const repayEvent = {
|
|
2587
2637
|
type: "event",
|
|
2588
|
-
name: "
|
|
2638
|
+
name: "Repay",
|
|
2589
2639
|
inputs: [
|
|
2590
2640
|
{
|
|
2591
2641
|
name: "caller",
|
|
2592
2642
|
type: "address",
|
|
2593
|
-
indexed:
|
|
2643
|
+
indexed: true,
|
|
2594
2644
|
internalType: "address"
|
|
2595
2645
|
},
|
|
2596
2646
|
{
|
|
@@ -2600,104 +2650,165 @@ const takeEvent = {
|
|
|
2600
2650
|
internalType: "bytes32"
|
|
2601
2651
|
},
|
|
2602
2652
|
{
|
|
2603
|
-
name: "
|
|
2653
|
+
name: "obligationUnits",
|
|
2654
|
+
type: "uint256",
|
|
2655
|
+
indexed: false,
|
|
2656
|
+
internalType: "uint256"
|
|
2657
|
+
},
|
|
2658
|
+
{
|
|
2659
|
+
name: "onBehalf",
|
|
2604
2660
|
type: "address",
|
|
2605
2661
|
indexed: true,
|
|
2606
2662
|
internalType: "address"
|
|
2607
|
-
}
|
|
2663
|
+
}
|
|
2664
|
+
],
|
|
2665
|
+
anonymous: false
|
|
2666
|
+
};
|
|
2667
|
+
/**
|
|
2668
|
+
* ABI for the Liquidate event emitted by the MorphoV2 contract.
|
|
2669
|
+
*/
|
|
2670
|
+
const liquidateEvent = {
|
|
2671
|
+
type: "event",
|
|
2672
|
+
name: "Liquidate",
|
|
2673
|
+
inputs: [
|
|
2608
2674
|
{
|
|
2609
|
-
name: "
|
|
2675
|
+
name: "caller",
|
|
2610
2676
|
type: "address",
|
|
2611
2677
|
indexed: true,
|
|
2612
2678
|
internalType: "address"
|
|
2613
2679
|
},
|
|
2614
2680
|
{
|
|
2615
|
-
name: "
|
|
2616
|
-
type: "
|
|
2617
|
-
indexed:
|
|
2618
|
-
internalType: "
|
|
2681
|
+
name: "id",
|
|
2682
|
+
type: "bytes32",
|
|
2683
|
+
indexed: true,
|
|
2684
|
+
internalType: "bytes32"
|
|
2619
2685
|
},
|
|
2620
2686
|
{
|
|
2621
|
-
name: "
|
|
2622
|
-
type: "
|
|
2687
|
+
name: "seizures",
|
|
2688
|
+
type: "tuple[]",
|
|
2623
2689
|
indexed: false,
|
|
2624
|
-
internalType: "
|
|
2690
|
+
internalType: "struct IMorphoV2.Seizure[]",
|
|
2691
|
+
components: [
|
|
2692
|
+
{
|
|
2693
|
+
name: "collateralIndex",
|
|
2694
|
+
type: "uint256",
|
|
2695
|
+
internalType: "uint256"
|
|
2696
|
+
},
|
|
2697
|
+
{
|
|
2698
|
+
name: "repaid",
|
|
2699
|
+
type: "uint256",
|
|
2700
|
+
internalType: "uint256"
|
|
2701
|
+
},
|
|
2702
|
+
{
|
|
2703
|
+
name: "seized",
|
|
2704
|
+
type: "uint256",
|
|
2705
|
+
internalType: "uint256"
|
|
2706
|
+
}
|
|
2707
|
+
]
|
|
2625
2708
|
},
|
|
2626
2709
|
{
|
|
2627
|
-
name: "
|
|
2628
|
-
type: "
|
|
2629
|
-
indexed:
|
|
2630
|
-
internalType: "
|
|
2710
|
+
name: "borrower",
|
|
2711
|
+
type: "address",
|
|
2712
|
+
indexed: true,
|
|
2713
|
+
internalType: "address"
|
|
2631
2714
|
},
|
|
2632
2715
|
{
|
|
2633
|
-
name: "
|
|
2716
|
+
name: "totalRepaid",
|
|
2634
2717
|
type: "uint256",
|
|
2635
2718
|
indexed: false,
|
|
2636
2719
|
internalType: "uint256"
|
|
2637
2720
|
},
|
|
2638
2721
|
{
|
|
2639
|
-
name: "
|
|
2722
|
+
name: "badDebt",
|
|
2640
2723
|
type: "uint256",
|
|
2641
2724
|
indexed: false,
|
|
2642
2725
|
internalType: "uint256"
|
|
2643
|
-
}
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
internalType: "bool"
|
|
2655
|
-
},
|
|
2726
|
+
}
|
|
2727
|
+
],
|
|
2728
|
+
anonymous: false
|
|
2729
|
+
};
|
|
2730
|
+
/**
|
|
2731
|
+
* ABI for the SupplyCollateral event emitted by the MorphoV2 contract.
|
|
2732
|
+
*/
|
|
2733
|
+
const supplyCollateralEvent = {
|
|
2734
|
+
type: "event",
|
|
2735
|
+
name: "SupplyCollateral",
|
|
2736
|
+
inputs: [
|
|
2656
2737
|
{
|
|
2657
|
-
name: "
|
|
2738
|
+
name: "caller",
|
|
2658
2739
|
type: "address",
|
|
2659
2740
|
indexed: false,
|
|
2660
2741
|
internalType: "address"
|
|
2661
2742
|
},
|
|
2662
2743
|
{
|
|
2663
|
-
name: "
|
|
2744
|
+
name: "id",
|
|
2664
2745
|
type: "bytes32",
|
|
2665
|
-
indexed:
|
|
2746
|
+
indexed: true,
|
|
2666
2747
|
internalType: "bytes32"
|
|
2667
2748
|
},
|
|
2668
2749
|
{
|
|
2669
|
-
name: "
|
|
2750
|
+
name: "collateral",
|
|
2751
|
+
type: "address",
|
|
2752
|
+
indexed: true,
|
|
2753
|
+
internalType: "address"
|
|
2754
|
+
},
|
|
2755
|
+
{
|
|
2756
|
+
name: "assets",
|
|
2670
2757
|
type: "uint256",
|
|
2671
2758
|
indexed: false,
|
|
2672
2759
|
internalType: "uint256"
|
|
2760
|
+
},
|
|
2761
|
+
{
|
|
2762
|
+
name: "onBehalf",
|
|
2763
|
+
type: "address",
|
|
2764
|
+
indexed: true,
|
|
2765
|
+
internalType: "address"
|
|
2673
2766
|
}
|
|
2674
2767
|
],
|
|
2675
2768
|
anonymous: false
|
|
2676
2769
|
};
|
|
2677
2770
|
/**
|
|
2678
|
-
* ABI for the
|
|
2771
|
+
* ABI for the WithdrawCollateral event emitted by the MorphoV2 contract.
|
|
2679
2772
|
*/
|
|
2680
|
-
const
|
|
2773
|
+
const withdrawCollateralEvent = {
|
|
2681
2774
|
type: "event",
|
|
2682
|
-
name: "
|
|
2775
|
+
name: "WithdrawCollateral",
|
|
2683
2776
|
inputs: [
|
|
2684
2777
|
{
|
|
2685
|
-
name: "
|
|
2778
|
+
name: "caller",
|
|
2686
2779
|
type: "address",
|
|
2687
|
-
indexed:
|
|
2780
|
+
indexed: false,
|
|
2688
2781
|
internalType: "address"
|
|
2689
2782
|
},
|
|
2690
2783
|
{
|
|
2691
|
-
name: "
|
|
2784
|
+
name: "id",
|
|
2692
2785
|
type: "bytes32",
|
|
2693
2786
|
indexed: true,
|
|
2694
2787
|
internalType: "bytes32"
|
|
2695
2788
|
},
|
|
2696
2789
|
{
|
|
2697
|
-
name: "
|
|
2790
|
+
name: "collateral",
|
|
2791
|
+
type: "address",
|
|
2792
|
+
indexed: true,
|
|
2793
|
+
internalType: "address"
|
|
2794
|
+
},
|
|
2795
|
+
{
|
|
2796
|
+
name: "assets",
|
|
2698
2797
|
type: "uint256",
|
|
2699
2798
|
indexed: false,
|
|
2700
2799
|
internalType: "uint256"
|
|
2800
|
+
},
|
|
2801
|
+
{
|
|
2802
|
+
name: "onBehalf",
|
|
2803
|
+
type: "address",
|
|
2804
|
+
indexed: true,
|
|
2805
|
+
internalType: "address"
|
|
2806
|
+
},
|
|
2807
|
+
{
|
|
2808
|
+
name: "receiver",
|
|
2809
|
+
type: "address",
|
|
2810
|
+
indexed: false,
|
|
2811
|
+
internalType: "address"
|
|
2701
2812
|
}
|
|
2702
2813
|
],
|
|
2703
2814
|
anonymous: false
|
|
@@ -2773,8 +2884,9 @@ function fromCollateral(parameters) {
|
|
|
2773
2884
|
* @returns The created oracles. {@link fromOffer.ReturnType}
|
|
2774
2885
|
*/
|
|
2775
2886
|
function fromOffer(parameters) {
|
|
2776
|
-
const { offer, blockNumber, price = null } = parameters;
|
|
2887
|
+
const { chainId, offer, blockNumber, price = null } = parameters;
|
|
2777
2888
|
return fromOffers({
|
|
2889
|
+
chainId,
|
|
2778
2890
|
offers: [offer],
|
|
2779
2891
|
blockNumber,
|
|
2780
2892
|
price
|
|
@@ -2788,13 +2900,13 @@ function fromOffer(parameters) {
|
|
|
2788
2900
|
* @returns The created oracles. {@link fromOffers.ReturnType}
|
|
2789
2901
|
*/
|
|
2790
2902
|
function fromOffers(parameters) {
|
|
2791
|
-
const { offers, blockNumber, price = null } = parameters;
|
|
2903
|
+
const { chainId, offers, blockNumber, price = null } = parameters;
|
|
2792
2904
|
const rowsByKey = /* @__PURE__ */ new Map();
|
|
2793
2905
|
for (const offer of offers) for (const collateral of offer.collaterals) {
|
|
2794
|
-
const key = `${
|
|
2906
|
+
const key = `${chainId}-${collateral.oracle}`.toLowerCase();
|
|
2795
2907
|
if (rowsByKey.has(key)) continue;
|
|
2796
2908
|
rowsByKey.set(key, fromCollateral({
|
|
2797
|
-
chainId
|
|
2909
|
+
chainId,
|
|
2798
2910
|
collateral,
|
|
2799
2911
|
blockNumber,
|
|
2800
2912
|
price
|
|
@@ -2819,11 +2931,14 @@ let Conversion;
|
|
|
2819
2931
|
//#region src/core/Position.ts
|
|
2820
2932
|
var Position_exports = /* @__PURE__ */ __exportAll({
|
|
2821
2933
|
Type: () => Type,
|
|
2822
|
-
from: () => from$12
|
|
2934
|
+
from: () => from$12,
|
|
2935
|
+
positionTypeId: () => positionTypeId
|
|
2823
2936
|
});
|
|
2824
2937
|
let Type = /* @__PURE__ */ function(Type) {
|
|
2825
2938
|
Type["ERC20"] = "erc20";
|
|
2826
2939
|
Type["VAULT_V1"] = "vault_v1";
|
|
2940
|
+
Type["DEBT_OF"] = "debtOf";
|
|
2941
|
+
Type["COLLATERAL_OF"] = "collateralOf";
|
|
2827
2942
|
return Type;
|
|
2828
2943
|
}({});
|
|
2829
2944
|
/**
|
|
@@ -2839,10 +2954,16 @@ function from$12(parameters) {
|
|
|
2839
2954
|
user: parameters.user.toLowerCase(),
|
|
2840
2955
|
type: parameters.type,
|
|
2841
2956
|
balance: parameters.balance,
|
|
2842
|
-
|
|
2957
|
+
asset: parameters.asset.toLowerCase(),
|
|
2843
2958
|
blockNumber: parameters.blockNumber
|
|
2844
2959
|
};
|
|
2845
2960
|
}
|
|
2961
|
+
/**
|
|
2962
|
+
* Maps a {@link Type} enum value to its 1-based integer ID used in the database.
|
|
2963
|
+
* @param type - The position type.
|
|
2964
|
+
* @returns The 1-based integer ID.
|
|
2965
|
+
*/
|
|
2966
|
+
const positionTypeId = (type) => Object.values(Type).indexOf(type) + 1;
|
|
2846
2967
|
|
|
2847
2968
|
//#endregion
|
|
2848
2969
|
//#region src/core/Tick.ts
|
|
@@ -2981,7 +3102,7 @@ function fromSnakeCase(snake) {
|
|
|
2981
3102
|
*/
|
|
2982
3103
|
function random() {
|
|
2983
3104
|
return from$11({
|
|
2984
|
-
obligationId:
|
|
3105
|
+
obligationId: hex(32),
|
|
2985
3106
|
ask: { tick: int(TICK_RANGE + 1) },
|
|
2986
3107
|
bid: { tick: int(TICK_RANGE + 1) }
|
|
2987
3108
|
});
|
|
@@ -3171,6 +3292,8 @@ function from$9(parameters) {
|
|
|
3171
3292
|
from: parameters.from.toLowerCase(),
|
|
3172
3293
|
to: parameters.to.toLowerCase(),
|
|
3173
3294
|
value: parameters.value,
|
|
3295
|
+
type: parameters.type,
|
|
3296
|
+
asset: parameters.asset.toLowerCase(),
|
|
3174
3297
|
blockNumber: parameters.blockNumber
|
|
3175
3298
|
};
|
|
3176
3299
|
}
|
|
@@ -3352,7 +3475,7 @@ const verifySignatureAndRecoverAddress = async (params) => {
|
|
|
3352
3475
|
const encode = async (tree, signature, domain) => {
|
|
3353
3476
|
const errorFactory = (reason) => new EncodeError(reason);
|
|
3354
3477
|
const normalizedDomain = normalizeSignatureDomain(domain, errorFactory);
|
|
3355
|
-
validateTreeForEncoding(tree
|
|
3478
|
+
validateTreeForEncoding(tree);
|
|
3356
3479
|
await verifySignatureAndRecoverAddress({
|
|
3357
3480
|
root: tree.root,
|
|
3358
3481
|
signature,
|
|
@@ -3384,14 +3507,10 @@ const encodeUnsigned = (tree) => {
|
|
|
3384
3507
|
validateTreeForEncoding(tree);
|
|
3385
3508
|
return (0, viem.bytesToHex)(encodeUnsignedBytes(tree));
|
|
3386
3509
|
};
|
|
3387
|
-
const validateTreeForEncoding = (tree
|
|
3510
|
+
const validateTreeForEncoding = (tree) => {
|
|
3388
3511
|
if (VERSION$1 > 255) throw new EncodeError(`version overflow: ${VERSION$1} exceeds 255`);
|
|
3389
3512
|
const computed = from$8(tree.offers);
|
|
3390
3513
|
if (tree.root !== computed.root) throw new EncodeError(`root mismatch: expected ${computed.root}, got ${tree.root}`);
|
|
3391
|
-
if (domain) {
|
|
3392
|
-
const mismatched = tree.offers.find((offer) => BigInt(offer.chainId) !== domain.chainId);
|
|
3393
|
-
if (mismatched) throw new EncodeError(`chainId mismatch: expected ${domain.chainId}, got ${mismatched.chainId}`);
|
|
3394
|
-
}
|
|
3395
3514
|
};
|
|
3396
3515
|
const encodeUnsignedBytes = (tree) => {
|
|
3397
3516
|
const offersPayload = tree.offers.map(serialize);
|
|
@@ -3458,8 +3577,6 @@ const decode = async (encoded, domain) => {
|
|
|
3458
3577
|
}
|
|
3459
3578
|
const tree = from$8(rawOffers.map((o) => OfferSchema().parse(o)));
|
|
3460
3579
|
if (root !== tree.root) throw new DecodeError(`root mismatch: expected ${tree.root}, got ${root}`);
|
|
3461
|
-
const chainIdMismatch = tree.offers.find((offer) => BigInt(offer.chainId) !== normalizedDomain.chainId);
|
|
3462
|
-
if (chainIdMismatch) throw new DecodeError(`chainId mismatch: expected ${normalizedDomain.chainId}, got ${chainIdMismatch.chainId}`);
|
|
3463
3580
|
return {
|
|
3464
3581
|
tree,
|
|
3465
3582
|
signature,
|
|
@@ -3512,7 +3629,7 @@ const BrandTypeId = Symbol.for("mempool/Brand");
|
|
|
3512
3629
|
|
|
3513
3630
|
//#endregion
|
|
3514
3631
|
//#region src/database/drizzle/VERSION.ts
|
|
3515
|
-
const VERSION = "router_v1.
|
|
3632
|
+
const VERSION = "router_v1.11";
|
|
3516
3633
|
|
|
3517
3634
|
//#endregion
|
|
3518
3635
|
//#region src/database/drizzle/schema.ts
|
|
@@ -3522,13 +3639,15 @@ var schema_exports = /* @__PURE__ */ __exportAll({
|
|
|
3522
3639
|
TABLE_NAMES: () => TABLE_NAMES,
|
|
3523
3640
|
VERSIONED_TABLE_NAMES: () => VERSIONED_TABLE_NAMES,
|
|
3524
3641
|
callbacks: () => callbacks,
|
|
3525
|
-
chains: () => chains
|
|
3642
|
+
chains: () => chains,
|
|
3526
3643
|
collectors: () => collectors,
|
|
3527
3644
|
consumedEvents: () => consumedEvents,
|
|
3528
3645
|
groups: () => groups,
|
|
3529
3646
|
lots: () => lots,
|
|
3647
|
+
lotsPositions: () => lotsPositions,
|
|
3530
3648
|
merklePaths: () => merklePaths,
|
|
3531
3649
|
obligationCollateralsV2: () => obligationCollateralsV2,
|
|
3650
|
+
obligationIdKeys: () => obligationIdKeys,
|
|
3532
3651
|
obligations: () => obligations,
|
|
3533
3652
|
offers: () => offers,
|
|
3534
3653
|
offersCallbacks: () => offersCallbacks,
|
|
@@ -3544,6 +3663,7 @@ var schema_exports = /* @__PURE__ */ __exportAll({
|
|
|
3544
3663
|
const s = (0, drizzle_orm_pg_core.pgSchema)(VERSION);
|
|
3545
3664
|
var EnumTableName = /* @__PURE__ */ function(EnumTableName) {
|
|
3546
3665
|
EnumTableName["OBLIGATIONS"] = "obligations";
|
|
3666
|
+
EnumTableName["OBLIGATION_ID_KEYS"] = "obligation_id_keys";
|
|
3547
3667
|
EnumTableName["GROUPS"] = "groups";
|
|
3548
3668
|
EnumTableName["CONSUMED_EVENTS"] = "consumed_events";
|
|
3549
3669
|
EnumTableName["OBLIGATION_COLLATERALS_V2"] = "obligation_collaterals_v2";
|
|
@@ -3557,6 +3677,7 @@ var EnumTableName = /* @__PURE__ */ function(EnumTableName) {
|
|
|
3557
3677
|
EnumTableName["COLLECTORS"] = "collectors";
|
|
3558
3678
|
EnumTableName["CHAINS"] = "chains";
|
|
3559
3679
|
EnumTableName["LOTS"] = "lots";
|
|
3680
|
+
EnumTableName["LOTS_POSITIONS"] = "lots_positions";
|
|
3560
3681
|
EnumTableName["OFFSETS"] = "offsets";
|
|
3561
3682
|
EnumTableName["TREES"] = "trees";
|
|
3562
3683
|
EnumTableName["MERKLE_PATHS"] = "merkle_paths";
|
|
@@ -3565,11 +3686,16 @@ var EnumTableName = /* @__PURE__ */ function(EnumTableName) {
|
|
|
3565
3686
|
const TABLE_NAMES = Object.values(EnumTableName);
|
|
3566
3687
|
const VERSIONED_TABLE_NAMES = TABLE_NAMES.map((table) => `"${VERSION}"."${table}"`);
|
|
3567
3688
|
const obligations = s.table(EnumTableName.OBLIGATIONS, {
|
|
3568
|
-
|
|
3569
|
-
chainId: (0, drizzle_orm_pg_core.bigint)("chain_id", { mode: "number" }).$type().notNull(),
|
|
3689
|
+
obligationKey: (0, drizzle_orm_pg_core.varchar)("obligation_key", { length: 66 }).primaryKey(),
|
|
3570
3690
|
loanToken: (0, drizzle_orm_pg_core.varchar)("loan_token", { length: 42 }).notNull(),
|
|
3571
3691
|
maturity: (0, drizzle_orm_pg_core.integer)("maturity").notNull()
|
|
3572
3692
|
});
|
|
3693
|
+
const obligationIdKeys = s.table(EnumTableName.OBLIGATION_ID_KEYS, {
|
|
3694
|
+
obligationId: (0, drizzle_orm_pg_core.varchar)("obligation_id", { length: 66 }).primaryKey(),
|
|
3695
|
+
obligationKey: (0, drizzle_orm_pg_core.varchar)("obligation_key", { length: 66 }).notNull().references(() => obligations.obligationKey, { onDelete: "cascade" }),
|
|
3696
|
+
chainId: (0, drizzle_orm_pg_core.bigint)("chain_id", { mode: "number" }).$type().notNull(),
|
|
3697
|
+
morphoV2: (0, drizzle_orm_pg_core.varchar)("morpho_v2", { length: 42 }).notNull()
|
|
3698
|
+
}, (table) => [(0, drizzle_orm_pg_core.index)("obligation_id_keys_obligation_key_idx").on(table.obligationKey), (0, drizzle_orm_pg_core.index)("obligation_id_keys_chain_id_idx").on(table.chainId)]);
|
|
3573
3699
|
const groups = s.table(EnumTableName.GROUPS, {
|
|
3574
3700
|
chainId: (0, drizzle_orm_pg_core.bigint)("chain_id", { mode: "number" }).$type().notNull(),
|
|
3575
3701
|
maker: (0, drizzle_orm_pg_core.varchar)("maker", { length: 42 }).notNull(),
|
|
@@ -3617,24 +3743,19 @@ const consumedEvents = s.table(EnumTableName.CONSUMED_EVENTS, {
|
|
|
3617
3743
|
(0, drizzle_orm_pg_core.index)("consumed_events_block_number_idx").on(t.blockNumber)
|
|
3618
3744
|
]);
|
|
3619
3745
|
const obligationCollateralsV2 = s.table(EnumTableName.OBLIGATION_COLLATERALS_V2, {
|
|
3620
|
-
|
|
3746
|
+
obligationKey: (0, drizzle_orm_pg_core.varchar)("obligation_key", { length: 66 }).notNull().references(() => obligations.obligationKey, { onDelete: "cascade" }),
|
|
3621
3747
|
asset: (0, drizzle_orm_pg_core.varchar)("asset", { length: 42 }).notNull(),
|
|
3622
|
-
oracleChainId: (0, drizzle_orm_pg_core.bigint)("oracle_chain_id", { mode: "number" }).$type().notNull(),
|
|
3623
3748
|
oracleAddress: (0, drizzle_orm_pg_core.varchar)("oracle_address", { length: 42 }).notNull(),
|
|
3624
3749
|
lltv: (0, drizzle_orm_pg_core.bigint)("lltv", { mode: "bigint" }).notNull(),
|
|
3750
|
+
collateralIndex: (0, drizzle_orm_pg_core.integer)("collateral_index").notNull(),
|
|
3625
3751
|
updatedAt: (0, drizzle_orm_pg_core.timestamp)("updated_at").defaultNow().notNull()
|
|
3626
3752
|
}, (table) => [
|
|
3627
3753
|
(0, drizzle_orm_pg_core.primaryKey)({
|
|
3628
|
-
columns: [table.
|
|
3754
|
+
columns: [table.obligationKey, table.asset],
|
|
3629
3755
|
name: "obligation_collaterals_v2_pk"
|
|
3630
3756
|
}),
|
|
3631
|
-
(0, drizzle_orm_pg_core.
|
|
3632
|
-
|
|
3633
|
-
foreignColumns: [oracles$1.chainId, oracles$1.address],
|
|
3634
|
-
name: "obligation_collaterals_v2_oracles_fk"
|
|
3635
|
-
}),
|
|
3636
|
-
(0, drizzle_orm_pg_core.index)("obligation_collaterals_v2_obligation_id_idx").on(table.obligationId),
|
|
3637
|
-
(0, drizzle_orm_pg_core.index)("obligation_collaterals_v2_oracle_fk_idx").on(table.oracleChainId, table.oracleAddress)
|
|
3757
|
+
(0, drizzle_orm_pg_core.index)("obligation_collaterals_v2_obligation_key_idx").on(table.obligationKey),
|
|
3758
|
+
(0, drizzle_orm_pg_core.index)("obligation_collaterals_v2_oracle_address_idx").on(table.oracleAddress)
|
|
3638
3759
|
]);
|
|
3639
3760
|
const oracles$1 = s.table(EnumTableName.ORACLES, {
|
|
3640
3761
|
chainId: (0, drizzle_orm_pg_core.bigint)("chain_id", { mode: "number" }).$type().notNull(),
|
|
@@ -3650,8 +3771,8 @@ const oracles$1 = s.table(EnumTableName.ORACLES, {
|
|
|
3650
3771
|
name: "oracles_pk"
|
|
3651
3772
|
})]);
|
|
3652
3773
|
const offers = s.table(EnumTableName.OFFERS, {
|
|
3653
|
-
hash: (0, drizzle_orm_pg_core.varchar)("hash", { length: 66 }).
|
|
3654
|
-
obligationId: (0, drizzle_orm_pg_core.varchar)("obligation_id", { length: 66 }).notNull().references(() =>
|
|
3774
|
+
hash: (0, drizzle_orm_pg_core.varchar)("hash", { length: 66 }).notNull(),
|
|
3775
|
+
obligationId: (0, drizzle_orm_pg_core.varchar)("obligation_id", { length: 66 }).notNull().references(() => obligationIdKeys.obligationId, { onDelete: "cascade" }),
|
|
3655
3776
|
assets: (0, drizzle_orm_pg_core.numeric)("assets", {
|
|
3656
3777
|
precision: 78,
|
|
3657
3778
|
scale: 0
|
|
@@ -3679,6 +3800,10 @@ const offers = s.table(EnumTableName.OFFERS, {
|
|
|
3679
3800
|
blockNumber: (0, drizzle_orm_pg_core.bigint)("block_number", { mode: "number" }).notNull(),
|
|
3680
3801
|
updatedAt: (0, drizzle_orm_pg_core.timestamp)("updated_at").defaultNow().notNull()
|
|
3681
3802
|
}, (table) => [
|
|
3803
|
+
(0, drizzle_orm_pg_core.primaryKey)({
|
|
3804
|
+
columns: [table.hash, table.obligationId],
|
|
3805
|
+
name: "offers_pk"
|
|
3806
|
+
}),
|
|
3682
3807
|
(0, drizzle_orm_pg_core.foreignKey)({
|
|
3683
3808
|
columns: [
|
|
3684
3809
|
table.groupChainId,
|
|
@@ -3697,10 +3822,19 @@ const offers = s.table(EnumTableName.OFFERS, {
|
|
|
3697
3822
|
(0, drizzle_orm_pg_core.index)("offers_obligation_id_side_idx").on(table.obligationId, table.buy)
|
|
3698
3823
|
]);
|
|
3699
3824
|
const offersCallbacks = s.table(EnumTableName.OFFERS_CALLBACKS, {
|
|
3700
|
-
offerHash: (0, drizzle_orm_pg_core.varchar)("offer_hash", { length: 66 }).notNull()
|
|
3825
|
+
offerHash: (0, drizzle_orm_pg_core.varchar)("offer_hash", { length: 66 }).notNull(),
|
|
3826
|
+
obligationId: (0, drizzle_orm_pg_core.varchar)("obligation_id", { length: 66 }).notNull(),
|
|
3701
3827
|
callbackId: (0, drizzle_orm_pg_core.varchar)("callback_id", { length: 66 })
|
|
3702
|
-
}, (table) => [(0, drizzle_orm_pg_core.
|
|
3703
|
-
columns: [table.offerHash, table.
|
|
3828
|
+
}, (table) => [(0, drizzle_orm_pg_core.foreignKey)({
|
|
3829
|
+
columns: [table.offerHash, table.obligationId],
|
|
3830
|
+
foreignColumns: [offers.hash, offers.obligationId],
|
|
3831
|
+
name: "offers_callbacks_offer_fk"
|
|
3832
|
+
}).onDelete("cascade"), (0, drizzle_orm_pg_core.primaryKey)({
|
|
3833
|
+
columns: [
|
|
3834
|
+
table.offerHash,
|
|
3835
|
+
table.obligationId,
|
|
3836
|
+
table.callbackId
|
|
3837
|
+
],
|
|
3704
3838
|
name: "offers_callbacks_pk"
|
|
3705
3839
|
})]);
|
|
3706
3840
|
const callbacks = s.table(EnumTableName.CALLBACKS, {
|
|
@@ -3708,23 +3842,25 @@ const callbacks = s.table(EnumTableName.CALLBACKS, {
|
|
|
3708
3842
|
positionChainId: (0, drizzle_orm_pg_core.bigint)("position_chain_id", { mode: "number" }).$type().notNull(),
|
|
3709
3843
|
positionContract: (0, drizzle_orm_pg_core.varchar)("position_contract", { length: 42 }).notNull(),
|
|
3710
3844
|
positionUser: (0, drizzle_orm_pg_core.varchar)("position_user", { length: 42 }).notNull(),
|
|
3845
|
+
positionTypeId: (0, drizzle_orm_pg_core.integer)("position_type_id").notNull().references(() => positionTypes.id, { onDelete: "no action" }),
|
|
3711
3846
|
amount: (0, drizzle_orm_pg_core.numeric)("amount", {
|
|
3712
3847
|
precision: 78,
|
|
3713
3848
|
scale: 0
|
|
3714
3849
|
})
|
|
3715
|
-
}
|
|
3850
|
+
});
|
|
3851
|
+
const lotsPositions = s.table(EnumTableName.LOTS_POSITIONS, {
|
|
3852
|
+
chainId: (0, drizzle_orm_pg_core.bigint)("chain_id", { mode: "number" }).$type().notNull(),
|
|
3853
|
+
contract: (0, drizzle_orm_pg_core.varchar)("contract", { length: 42 }).notNull(),
|
|
3854
|
+
user: (0, drizzle_orm_pg_core.varchar)("user", { length: 42 }).notNull(),
|
|
3855
|
+
positionTypeId: (0, drizzle_orm_pg_core.integer)("position_type_id").notNull().references(() => positionTypes.id, { onDelete: "no action" })
|
|
3856
|
+
}, (table) => [(0, drizzle_orm_pg_core.primaryKey)({
|
|
3716
3857
|
columns: [
|
|
3717
|
-
table.
|
|
3718
|
-
table.
|
|
3719
|
-
table.
|
|
3720
|
-
],
|
|
3721
|
-
foreignColumns: [
|
|
3722
|
-
positions.chainId,
|
|
3723
|
-
positions.contract,
|
|
3724
|
-
positions.user
|
|
3858
|
+
table.chainId,
|
|
3859
|
+
table.contract,
|
|
3860
|
+
table.user
|
|
3725
3861
|
],
|
|
3726
|
-
name: "
|
|
3727
|
-
})
|
|
3862
|
+
name: "lots_positions_pk"
|
|
3863
|
+
})]);
|
|
3728
3864
|
const lots = s.table(EnumTableName.LOTS, {
|
|
3729
3865
|
chainId: (0, drizzle_orm_pg_core.bigint)("chain_id", { mode: "number" }).$type().notNull(),
|
|
3730
3866
|
user: (0, drizzle_orm_pg_core.varchar)("user", { length: 42 }).notNull(),
|
|
@@ -3757,11 +3893,11 @@ const lots = s.table(EnumTableName.LOTS, {
|
|
|
3757
3893
|
table.user
|
|
3758
3894
|
],
|
|
3759
3895
|
foreignColumns: [
|
|
3760
|
-
|
|
3761
|
-
|
|
3762
|
-
|
|
3896
|
+
lotsPositions.chainId,
|
|
3897
|
+
lotsPositions.contract,
|
|
3898
|
+
lotsPositions.user
|
|
3763
3899
|
],
|
|
3764
|
-
name: "
|
|
3900
|
+
name: "lots_lots_positions_fk"
|
|
3765
3901
|
}).onDelete("cascade"),
|
|
3766
3902
|
(0, drizzle_orm_pg_core.foreignKey)({
|
|
3767
3903
|
columns: [
|
|
@@ -3803,11 +3939,11 @@ const offsets = s.table(EnumTableName.OFFSETS, {
|
|
|
3803
3939
|
table.user
|
|
3804
3940
|
],
|
|
3805
3941
|
foreignColumns: [
|
|
3806
|
-
|
|
3807
|
-
|
|
3808
|
-
|
|
3942
|
+
lotsPositions.chainId,
|
|
3943
|
+
lotsPositions.contract,
|
|
3944
|
+
lotsPositions.user
|
|
3809
3945
|
],
|
|
3810
|
-
name: "
|
|
3946
|
+
name: "offsets_lots_positions_fk"
|
|
3811
3947
|
}).onDelete("cascade")]);
|
|
3812
3948
|
const PositionTypes = s.enum("position_type", Object.values(Type));
|
|
3813
3949
|
const positionTypes = s.table("position_types", {
|
|
@@ -3816,34 +3952,38 @@ const positionTypes = s.table("position_types", {
|
|
|
3816
3952
|
});
|
|
3817
3953
|
const positions = s.table(EnumTableName.POSITIONS, {
|
|
3818
3954
|
chainId: (0, drizzle_orm_pg_core.bigint)("chain_id", { mode: "number" }).$type().notNull(),
|
|
3819
|
-
contract: (0, drizzle_orm_pg_core.varchar)("contract", { length:
|
|
3955
|
+
contract: (0, drizzle_orm_pg_core.varchar)("contract", { length: 66 }).notNull(),
|
|
3820
3956
|
user: (0, drizzle_orm_pg_core.varchar)("user", { length: 42 }).notNull(),
|
|
3821
3957
|
positionTypeId: (0, drizzle_orm_pg_core.integer)("position_type_id").notNull().references(() => positionTypes.id, { onDelete: "no action" }),
|
|
3822
3958
|
balance: (0, drizzle_orm_pg_core.numeric)("balance", {
|
|
3823
3959
|
precision: 78,
|
|
3824
3960
|
scale: 0
|
|
3825
3961
|
}),
|
|
3826
|
-
asset: (0, drizzle_orm_pg_core.varchar)("asset", { length: 42 }),
|
|
3962
|
+
asset: (0, drizzle_orm_pg_core.varchar)("asset", { length: 42 }).notNull(),
|
|
3827
3963
|
blockNumber: (0, drizzle_orm_pg_core.bigint)("block_number", { mode: "number" }).notNull(),
|
|
3828
3964
|
updatedAt: (0, drizzle_orm_pg_core.timestamp)("updated_at").defaultNow().notNull()
|
|
3829
3965
|
}, (table) => [(0, drizzle_orm_pg_core.primaryKey)({
|
|
3830
3966
|
columns: [
|
|
3831
3967
|
table.chainId,
|
|
3832
3968
|
table.contract,
|
|
3833
|
-
table.user
|
|
3969
|
+
table.user,
|
|
3970
|
+
table.positionTypeId,
|
|
3971
|
+
table.asset
|
|
3834
3972
|
],
|
|
3835
3973
|
name: "positions_pk"
|
|
3836
3974
|
})]);
|
|
3837
3975
|
const transfers = s.table(EnumTableName.TRANSFERS, {
|
|
3838
3976
|
eventId: (0, drizzle_orm_pg_core.varchar)("event_id", { length: 128 }).primaryKey(),
|
|
3839
3977
|
chainId: (0, drizzle_orm_pg_core.bigint)("chain_id", { mode: "number" }).$type().notNull(),
|
|
3840
|
-
contract: (0, drizzle_orm_pg_core.varchar)("contract", { length:
|
|
3978
|
+
contract: (0, drizzle_orm_pg_core.varchar)("contract", { length: 66 }).notNull(),
|
|
3841
3979
|
from: (0, drizzle_orm_pg_core.varchar)("from", { length: 42 }).notNull(),
|
|
3842
3980
|
to: (0, drizzle_orm_pg_core.varchar)("to", { length: 42 }).notNull(),
|
|
3843
3981
|
value: (0, drizzle_orm_pg_core.numeric)("value", {
|
|
3844
3982
|
precision: 78,
|
|
3845
3983
|
scale: 0
|
|
3846
3984
|
}).notNull(),
|
|
3985
|
+
positionTypeId: (0, drizzle_orm_pg_core.integer)("position_type_id").notNull().references(() => positionTypes.id, { onDelete: "no action" }),
|
|
3986
|
+
asset: (0, drizzle_orm_pg_core.varchar)("asset", { length: 42 }).notNull(),
|
|
3847
3987
|
blockNumber: (0, drizzle_orm_pg_core.bigint)("block_number", { mode: "number" }).notNull(),
|
|
3848
3988
|
createdAt: (0, drizzle_orm_pg_core.timestamp)("created_at").defaultNow().notNull()
|
|
3849
3989
|
}, (table) => [
|
|
@@ -3851,12 +3991,16 @@ const transfers = s.table(EnumTableName.TRANSFERS, {
|
|
|
3851
3991
|
columns: [
|
|
3852
3992
|
table.chainId,
|
|
3853
3993
|
table.contract,
|
|
3854
|
-
table.from
|
|
3994
|
+
table.from,
|
|
3995
|
+
table.positionTypeId,
|
|
3996
|
+
table.asset
|
|
3855
3997
|
],
|
|
3856
3998
|
foreignColumns: [
|
|
3857
3999
|
positions.chainId,
|
|
3858
4000
|
positions.contract,
|
|
3859
|
-
positions.user
|
|
4001
|
+
positions.user,
|
|
4002
|
+
positions.positionTypeId,
|
|
4003
|
+
positions.asset
|
|
3860
4004
|
],
|
|
3861
4005
|
name: "transfers_positions_from_fk"
|
|
3862
4006
|
}).onDelete("cascade"),
|
|
@@ -3864,16 +4008,21 @@ const transfers = s.table(EnumTableName.TRANSFERS, {
|
|
|
3864
4008
|
columns: [
|
|
3865
4009
|
table.chainId,
|
|
3866
4010
|
table.contract,
|
|
3867
|
-
table.to
|
|
4011
|
+
table.to,
|
|
4012
|
+
table.positionTypeId,
|
|
4013
|
+
table.asset
|
|
3868
4014
|
],
|
|
3869
4015
|
foreignColumns: [
|
|
3870
4016
|
positions.chainId,
|
|
3871
4017
|
positions.contract,
|
|
3872
|
-
positions.user
|
|
4018
|
+
positions.user,
|
|
4019
|
+
positions.positionTypeId,
|
|
4020
|
+
positions.asset
|
|
3873
4021
|
],
|
|
3874
4022
|
name: "transfers_positions_to_fk"
|
|
3875
4023
|
}).onDelete("cascade"),
|
|
3876
|
-
(0, drizzle_orm_pg_core.index)("transfers_chain_contract_user_idx").on(table.chainId, table.contract, table.from, table.to, table.blockNumber)
|
|
4024
|
+
(0, drizzle_orm_pg_core.index)("transfers_chain_contract_user_idx").on(table.chainId, table.contract, table.from, table.to, table.blockNumber),
|
|
4025
|
+
(0, drizzle_orm_pg_core.index)("transfers_chain_type_block_idx").on(table.chainId, table.positionTypeId, table.blockNumber)
|
|
3877
4026
|
]);
|
|
3878
4027
|
const StatusCode = s.enum("status_code", Object.values(Status));
|
|
3879
4028
|
const status = s.table("status", {
|
|
@@ -3881,12 +4030,20 @@ const status = s.table("status", {
|
|
|
3881
4030
|
code: StatusCode("code").unique()
|
|
3882
4031
|
});
|
|
3883
4032
|
const validations = s.table("validations", {
|
|
3884
|
-
offerHash: (0, drizzle_orm_pg_core.varchar)("offer_hash", { length: 66 }).
|
|
4033
|
+
offerHash: (0, drizzle_orm_pg_core.varchar)("offer_hash", { length: 66 }).notNull(),
|
|
4034
|
+
obligationId: (0, drizzle_orm_pg_core.varchar)("obligation_id", { length: 66 }).notNull(),
|
|
3885
4035
|
statusId: (0, drizzle_orm_pg_core.integer)("status_id").notNull().references(() => status.id, { onDelete: "no action" }),
|
|
3886
4036
|
updatedAt: (0, drizzle_orm_pg_core.timestamp)("updated_at").defaultNow().notNull()
|
|
3887
|
-
})
|
|
4037
|
+
}, (table) => [(0, drizzle_orm_pg_core.primaryKey)({
|
|
4038
|
+
columns: [table.offerHash, table.obligationId],
|
|
4039
|
+
name: "validations_pk"
|
|
4040
|
+
}), (0, drizzle_orm_pg_core.foreignKey)({
|
|
4041
|
+
columns: [table.offerHash, table.obligationId],
|
|
4042
|
+
foreignColumns: [offers.hash, offers.obligationId],
|
|
4043
|
+
name: "validations_offer_fk"
|
|
4044
|
+
}).onDelete("cascade")]);
|
|
3888
4045
|
const collectors = s.table(EnumTableName.COLLECTORS, {
|
|
3889
|
-
chainId: (0, drizzle_orm_pg_core.bigint)("chain_id", { mode: "number" }).$type().notNull().references(() => chains
|
|
4046
|
+
chainId: (0, drizzle_orm_pg_core.bigint)("chain_id", { mode: "number" }).$type().notNull().references(() => chains.chainId, { onDelete: "no action" }),
|
|
3890
4047
|
name: (0, drizzle_orm_pg_core.text)("name").$type().notNull(),
|
|
3891
4048
|
blockNumber: (0, drizzle_orm_pg_core.bigint)("block_number", { mode: "number" }).notNull(),
|
|
3892
4049
|
epoch: (0, drizzle_orm_pg_core.numeric)("epoch", {
|
|
@@ -3895,7 +4052,7 @@ const collectors = s.table(EnumTableName.COLLECTORS, {
|
|
|
3895
4052
|
}).default("0").notNull(),
|
|
3896
4053
|
updatedAt: (0, drizzle_orm_pg_core.timestamp)("updated_at").defaultNow().notNull()
|
|
3897
4054
|
}, (table) => [(0, drizzle_orm_pg_core.uniqueIndex)("collectors_chain_name_idx").on(table.chainId, table.name)]);
|
|
3898
|
-
const chains
|
|
4055
|
+
const chains = s.table(EnumTableName.CHAINS, {
|
|
3899
4056
|
chainId: (0, drizzle_orm_pg_core.bigint)("chain_id", { mode: "number" }).$type().notNull(),
|
|
3900
4057
|
blockNumber: (0, drizzle_orm_pg_core.bigint)("block_number", { mode: "number" }).notNull(),
|
|
3901
4058
|
epoch: (0, drizzle_orm_pg_core.numeric)("epoch", {
|
|
@@ -3910,18 +4067,352 @@ const trees = s.table(EnumTableName.TREES, {
|
|
|
3910
4067
|
createdAt: (0, drizzle_orm_pg_core.timestamp)("created_at").defaultNow().notNull()
|
|
3911
4068
|
});
|
|
3912
4069
|
const merklePaths = s.table(EnumTableName.MERKLE_PATHS, {
|
|
3913
|
-
offerHash: (0, drizzle_orm_pg_core.varchar)("offer_hash", { length: 66 }).
|
|
4070
|
+
offerHash: (0, drizzle_orm_pg_core.varchar)("offer_hash", { length: 66 }).notNull(),
|
|
4071
|
+
obligationId: (0, drizzle_orm_pg_core.varchar)("obligation_id", { length: 66 }).notNull(),
|
|
3914
4072
|
treeRoot: (0, drizzle_orm_pg_core.varchar)("tree_root", { length: 66 }).notNull().references(() => trees.root, { onDelete: "cascade" }),
|
|
3915
4073
|
proofNodes: (0, drizzle_orm_pg_core.text)("proof_nodes").notNull(),
|
|
3916
4074
|
createdAt: (0, drizzle_orm_pg_core.timestamp)("created_at").defaultNow().notNull()
|
|
3917
|
-
}, (table) => [
|
|
4075
|
+
}, (table) => [
|
|
4076
|
+
(0, drizzle_orm_pg_core.primaryKey)({
|
|
4077
|
+
columns: [table.offerHash, table.obligationId],
|
|
4078
|
+
name: "merkle_paths_pk"
|
|
4079
|
+
}),
|
|
4080
|
+
(0, drizzle_orm_pg_core.foreignKey)({
|
|
4081
|
+
columns: [table.offerHash, table.obligationId],
|
|
4082
|
+
foreignColumns: [offers.hash, offers.obligationId],
|
|
4083
|
+
name: "merkle_paths_offer_fk"
|
|
4084
|
+
}).onDelete("cascade"),
|
|
4085
|
+
(0, drizzle_orm_pg_core.index)("merkle_paths_tree_root_idx").on(table.treeRoot)
|
|
4086
|
+
]);
|
|
4087
|
+
|
|
4088
|
+
//#endregion
|
|
4089
|
+
//#region src/indexer/collectors/CollectFunctions/processors/processCollateralSeizures.ts
|
|
4090
|
+
/**
|
|
4091
|
+
* Parse raw MorphoV2 liquidate logs and compute collateral seizures.
|
|
4092
|
+
*
|
|
4093
|
+
* Seizures only expose `(obligationId, collateralIndex)` and must be resolved
|
|
4094
|
+
* to collateral token addresses before creating transfer rows.
|
|
4095
|
+
*
|
|
4096
|
+
* @param parameters - The parsed event logs and chain ID.
|
|
4097
|
+
* @param parameters.logs - Parsed event logs from MorphoV2.
|
|
4098
|
+
* @param parameters.chainId - Chain ID for event attribution.
|
|
4099
|
+
* @returns Seizure events pending collateral address resolution.
|
|
4100
|
+
*/
|
|
4101
|
+
function processCollateralSeizures(parameters) {
|
|
4102
|
+
const { logs, chainId } = parameters;
|
|
4103
|
+
const logger = getLogger();
|
|
4104
|
+
const seizureEvents = [];
|
|
4105
|
+
for (const rawLog of logs) {
|
|
4106
|
+
if (rawLog.blockNumber === null || rawLog.logIndex === null || rawLog.transactionHash === null) {
|
|
4107
|
+
logger.debug({
|
|
4108
|
+
chainId,
|
|
4109
|
+
msg: "Skipping collateral log because it is missing required fields"
|
|
4110
|
+
});
|
|
4111
|
+
continue;
|
|
4112
|
+
}
|
|
4113
|
+
if (rawLog.eventName !== liquidateEvent.name) continue;
|
|
4114
|
+
const args = rawLog.args;
|
|
4115
|
+
if (args?.id === void 0 || args?.borrower === void 0 || args?.seizures === void 0) {
|
|
4116
|
+
logger.debug({
|
|
4117
|
+
chainId,
|
|
4118
|
+
msg: "Skipping Liquidate log for collateral because it is missing required args"
|
|
4119
|
+
});
|
|
4120
|
+
continue;
|
|
4121
|
+
}
|
|
4122
|
+
const baseId = `${rawLog.blockNumber.toString()}-${rawLog.logIndex.toString()}-${chainId}-${rawLog.transactionHash}`;
|
|
4123
|
+
for (let seizureIndex = 0; seizureIndex < args.seizures.length; seizureIndex++) {
|
|
4124
|
+
const seizure = args.seizures[seizureIndex];
|
|
4125
|
+
if (seizure.seized === 0n) continue;
|
|
4126
|
+
seizureEvents.push({
|
|
4127
|
+
id: `${baseId}-collateral-liquidate-${seizureIndex}`,
|
|
4128
|
+
chainId,
|
|
4129
|
+
obligationId: args.id,
|
|
4130
|
+
collateralIndex: Number(seizure.collateralIndex),
|
|
4131
|
+
user: args.borrower,
|
|
4132
|
+
amount: seizure.seized,
|
|
4133
|
+
blockNumber: Number(rawLog.blockNumber)
|
|
4134
|
+
});
|
|
4135
|
+
}
|
|
4136
|
+
}
|
|
4137
|
+
return seizureEvents;
|
|
4138
|
+
}
|
|
4139
|
+
|
|
4140
|
+
//#endregion
|
|
4141
|
+
//#region src/indexer/collectors/CollectFunctions/processors/processCollateralTransfers.ts
|
|
4142
|
+
/**
|
|
4143
|
+
* Parse raw MorphoV2 logs and compute collateral transfers.
|
|
4144
|
+
*
|
|
4145
|
+
* A collateral position uses `contract = obligationId` and `asset = collateral token address`.
|
|
4146
|
+
* The 5-col PK `(chainId, contract, user, positionTypeId, asset)` distinguishes per-token positions.
|
|
4147
|
+
*
|
|
4148
|
+
* **SupplyCollateral**: Transfer from zeroAddress to onBehalf (supply)
|
|
4149
|
+
* **WithdrawCollateral**: Transfer from onBehalf to zeroAddress (withdrawal)
|
|
4150
|
+
*
|
|
4151
|
+
* @param parameters - The parsed event logs and chain ID.
|
|
4152
|
+
* @param parameters.logs - Parsed event logs from MorphoV2.
|
|
4153
|
+
* @param parameters.chainId - Chain ID for event attribution.
|
|
4154
|
+
* @returns Collateral transfers from SupplyCollateral/WithdrawCollateral.
|
|
4155
|
+
*/
|
|
4156
|
+
function processCollateralTransfers(parameters) {
|
|
4157
|
+
const { logs, chainId } = parameters;
|
|
4158
|
+
const logger = getLogger();
|
|
4159
|
+
const transfers = [];
|
|
4160
|
+
for (const rawLog of logs) {
|
|
4161
|
+
if (rawLog.blockNumber === null || rawLog.logIndex === null || rawLog.transactionHash === null) {
|
|
4162
|
+
logger.debug({
|
|
4163
|
+
chainId,
|
|
4164
|
+
msg: "Skipping collateral log because it is missing required fields"
|
|
4165
|
+
});
|
|
4166
|
+
continue;
|
|
4167
|
+
}
|
|
4168
|
+
const eventName = rawLog.eventName;
|
|
4169
|
+
const baseId = `${rawLog.blockNumber.toString()}-${rawLog.logIndex.toString()}-${chainId}-${rawLog.transactionHash}`;
|
|
4170
|
+
if (eventName === supplyCollateralEvent.name) {
|
|
4171
|
+
const args = rawLog.args;
|
|
4172
|
+
if (args?.id === void 0 || args?.collateral === void 0 || args?.assets === void 0 || args?.onBehalf === void 0) {
|
|
4173
|
+
logger.debug({
|
|
4174
|
+
chainId,
|
|
4175
|
+
msg: "Skipping SupplyCollateral log because it is missing required args"
|
|
4176
|
+
});
|
|
4177
|
+
continue;
|
|
4178
|
+
}
|
|
4179
|
+
if (args.assets === 0n) continue;
|
|
4180
|
+
transfers.push(from$9({
|
|
4181
|
+
id: `${baseId}-collateral-supply`,
|
|
4182
|
+
chainId,
|
|
4183
|
+
contract: args.id,
|
|
4184
|
+
from: viem.zeroAddress,
|
|
4185
|
+
to: args.onBehalf,
|
|
4186
|
+
value: args.assets,
|
|
4187
|
+
type: Type.COLLATERAL_OF,
|
|
4188
|
+
asset: args.collateral,
|
|
4189
|
+
blockNumber: Number(rawLog.blockNumber)
|
|
4190
|
+
}));
|
|
4191
|
+
continue;
|
|
4192
|
+
}
|
|
4193
|
+
if (eventName === withdrawCollateralEvent.name) {
|
|
4194
|
+
const args = rawLog.args;
|
|
4195
|
+
if (args?.id === void 0 || args?.collateral === void 0 || args?.assets === void 0 || args?.onBehalf === void 0) {
|
|
4196
|
+
logger.debug({
|
|
4197
|
+
chainId,
|
|
4198
|
+
msg: "Skipping WithdrawCollateral log because it is missing required args"
|
|
4199
|
+
});
|
|
4200
|
+
continue;
|
|
4201
|
+
}
|
|
4202
|
+
if (args.assets === 0n) continue;
|
|
4203
|
+
transfers.push(from$9({
|
|
4204
|
+
id: `${baseId}-collateral-withdraw`,
|
|
4205
|
+
chainId,
|
|
4206
|
+
contract: args.id,
|
|
4207
|
+
from: args.onBehalf,
|
|
4208
|
+
to: viem.zeroAddress,
|
|
4209
|
+
value: args.assets,
|
|
4210
|
+
type: Type.COLLATERAL_OF,
|
|
4211
|
+
asset: args.collateral,
|
|
4212
|
+
blockNumber: Number(rawLog.blockNumber)
|
|
4213
|
+
}));
|
|
4214
|
+
}
|
|
4215
|
+
}
|
|
4216
|
+
return transfers;
|
|
4217
|
+
}
|
|
3918
4218
|
|
|
3919
4219
|
//#endregion
|
|
3920
|
-
//#region src/indexer/collectors/CollectFunctions/
|
|
4220
|
+
//#region src/indexer/collectors/CollectFunctions/processors/processConsumedLogs.ts
|
|
3921
4221
|
const buildGroupKey = (parameters) => {
|
|
3922
4222
|
return `${parameters.chainId}-${parameters.maker.toLowerCase()}-${parameters.group.toLowerCase()}`;
|
|
3923
4223
|
};
|
|
3924
|
-
|
|
4224
|
+
/** Parse raw MorphoV2 logs and produce normalized consumed events.
|
|
4225
|
+
* @param parameters - The parsed event logs and chain ID.
|
|
4226
|
+
* @param parameters.logs - Parsed event logs from MorphoV2 (Consume and Take events).
|
|
4227
|
+
* @param parameters.chainId - Chain ID for event attribution.
|
|
4228
|
+
* @returns Flat array of consumed events.
|
|
4229
|
+
*/
|
|
4230
|
+
function processConsumedLogs(parameters) {
|
|
4231
|
+
const { logs, chainId } = parameters;
|
|
4232
|
+
const logger = getLogger();
|
|
4233
|
+
const consumedEvents = [];
|
|
4234
|
+
for (const rawLog of logs) {
|
|
4235
|
+
if (rawLog.blockNumber === null || rawLog.logIndex === null || rawLog.transactionHash === null) {
|
|
4236
|
+
logger.debug({
|
|
4237
|
+
chainId,
|
|
4238
|
+
msg: "Skipping log because it is missing required fields"
|
|
4239
|
+
});
|
|
4240
|
+
continue;
|
|
4241
|
+
}
|
|
4242
|
+
const eventName = rawLog.eventName;
|
|
4243
|
+
if (eventName === consumedEvent.name) {
|
|
4244
|
+
const consumeArgs = rawLog.args;
|
|
4245
|
+
if (consumeArgs?.user === void 0 || consumeArgs?.group === void 0 || consumeArgs?.amount === void 0) {
|
|
4246
|
+
logger.debug({
|
|
4247
|
+
chainId,
|
|
4248
|
+
msg: "Skipping Consume log because it is missing required args"
|
|
4249
|
+
});
|
|
4250
|
+
continue;
|
|
4251
|
+
}
|
|
4252
|
+
consumedEvents.push({
|
|
4253
|
+
kind: "consume",
|
|
4254
|
+
id: `${rawLog.blockNumber.toString()}-${rawLog.logIndex.toString()}-${chainId}-${rawLog.transactionHash}`,
|
|
4255
|
+
chainId,
|
|
4256
|
+
maker: consumeArgs.user,
|
|
4257
|
+
group: consumeArgs.group,
|
|
4258
|
+
amount: consumeArgs.amount,
|
|
4259
|
+
blockNumber: Number(rawLog.blockNumber)
|
|
4260
|
+
});
|
|
4261
|
+
continue;
|
|
4262
|
+
}
|
|
4263
|
+
if (eventName === takeEvent.name) {
|
|
4264
|
+
const takeArgs = rawLog.args;
|
|
4265
|
+
if (takeArgs?.maker === void 0 || takeArgs?.group === void 0 || takeArgs?.consumed === void 0) {
|
|
4266
|
+
logger.debug({
|
|
4267
|
+
chainId,
|
|
4268
|
+
msg: "Skipping Take log because it is missing required args for consumed"
|
|
4269
|
+
});
|
|
4270
|
+
continue;
|
|
4271
|
+
}
|
|
4272
|
+
consumedEvents.push({
|
|
4273
|
+
kind: "take",
|
|
4274
|
+
id: `${rawLog.blockNumber.toString()}-${rawLog.logIndex.toString()}-${chainId}-${rawLog.transactionHash}`,
|
|
4275
|
+
chainId,
|
|
4276
|
+
maker: takeArgs.maker,
|
|
4277
|
+
group: takeArgs.group,
|
|
4278
|
+
consumed: takeArgs.consumed,
|
|
4279
|
+
blockNumber: Number(rawLog.blockNumber)
|
|
4280
|
+
});
|
|
4281
|
+
}
|
|
4282
|
+
}
|
|
4283
|
+
return consumedEvents;
|
|
4284
|
+
}
|
|
4285
|
+
|
|
4286
|
+
//#endregion
|
|
4287
|
+
//#region src/indexer/collectors/CollectFunctions/processors/processDebtTransfers.ts
|
|
4288
|
+
/**
|
|
4289
|
+
* Parse raw MorphoV2 logs and compute debt transfers.
|
|
4290
|
+
*
|
|
4291
|
+
* A debt is modeled as a negative position: borrowing = transfer FROM user TO zeroAddress,
|
|
4292
|
+
* repayment = FROM zeroAddress TO user. The contract field is the obligationId.
|
|
4293
|
+
*
|
|
4294
|
+
* Applies the 4-case Take matrix, Repay, and Liquidate attribution rules:
|
|
4295
|
+
*
|
|
4296
|
+
* **Take event** — Buyer = maker if offerIsBuy, taker otherwise. Seller = the other.
|
|
4297
|
+
* | buyerIsLender | sellerIsBorrower | Buyer transfer | Seller transfer |
|
|
4298
|
+
* |---------------|------------------|------------------------------|------------------------------|
|
|
4299
|
+
* | true | true | none | from: seller → to: 0x0 |
|
|
4300
|
+
* | true | false | none | none |
|
|
4301
|
+
* | false | true | from: 0x0 → to: buyer | from: seller → to: 0x0 |
|
|
4302
|
+
* | false | false | from: 0x0 → to: buyer | none |
|
|
4303
|
+
*
|
|
4304
|
+
* **Repay**: from: 0x0 → to: onBehalf
|
|
4305
|
+
* **Liquidate**: from: 0x0 → to: borrower (value = totalRepaid + badDebt)
|
|
4306
|
+
*
|
|
4307
|
+
* @param parameters - The parsed event logs and chain ID.
|
|
4308
|
+
* @param parameters.logs - Parsed event logs from MorphoV2 (Take, Repay, Liquidate events).
|
|
4309
|
+
* @param parameters.chainId - Chain ID for event attribution.
|
|
4310
|
+
* @returns Transfer events ready for DB insertion.
|
|
4311
|
+
*/
|
|
4312
|
+
function processDebtTransfers(parameters) {
|
|
4313
|
+
const { logs, chainId } = parameters;
|
|
4314
|
+
const logger = getLogger();
|
|
4315
|
+
const transfers = [];
|
|
4316
|
+
for (const rawLog of logs) {
|
|
4317
|
+
if (rawLog.blockNumber === null || rawLog.logIndex === null || rawLog.transactionHash === null) {
|
|
4318
|
+
logger.debug({
|
|
4319
|
+
chainId,
|
|
4320
|
+
msg: "Skipping debt log because it is missing required fields"
|
|
4321
|
+
});
|
|
4322
|
+
continue;
|
|
4323
|
+
}
|
|
4324
|
+
const eventName = rawLog.eventName;
|
|
4325
|
+
const baseId = `${rawLog.blockNumber.toString()}-${rawLog.logIndex.toString()}-${chainId}-${rawLog.transactionHash}`;
|
|
4326
|
+
if (eventName === takeEvent.name) {
|
|
4327
|
+
const args = rawLog.args;
|
|
4328
|
+
if (args?.id === void 0 || args?.maker === void 0 || args?.taker === void 0 || args?.offerIsBuy === void 0 || args?.obligationUnits === void 0 || args?.buyerIsLender === void 0 || args?.sellerIsBorrower === void 0) {
|
|
4329
|
+
logger.debug({
|
|
4330
|
+
chainId,
|
|
4331
|
+
msg: "Skipping Take log because it is missing required args for debt"
|
|
4332
|
+
});
|
|
4333
|
+
continue;
|
|
4334
|
+
}
|
|
4335
|
+
if (args.obligationUnits === 0n) continue;
|
|
4336
|
+
const buyer = args.offerIsBuy ? args.maker : args.taker;
|
|
4337
|
+
const seller = args.offerIsBuy ? args.taker : args.maker;
|
|
4338
|
+
const blockNumber = Number(rawLog.blockNumber);
|
|
4339
|
+
if (!args.buyerIsLender) transfers.push(from$9({
|
|
4340
|
+
id: `${baseId}-debt-buyer`,
|
|
4341
|
+
chainId,
|
|
4342
|
+
contract: args.id,
|
|
4343
|
+
from: viem.zeroAddress,
|
|
4344
|
+
to: buyer,
|
|
4345
|
+
value: args.obligationUnits,
|
|
4346
|
+
type: Type.DEBT_OF,
|
|
4347
|
+
asset: viem.zeroAddress,
|
|
4348
|
+
blockNumber
|
|
4349
|
+
}));
|
|
4350
|
+
if (args.sellerIsBorrower) transfers.push(from$9({
|
|
4351
|
+
id: `${baseId}-debt-seller`,
|
|
4352
|
+
chainId,
|
|
4353
|
+
contract: args.id,
|
|
4354
|
+
from: seller,
|
|
4355
|
+
to: viem.zeroAddress,
|
|
4356
|
+
value: args.obligationUnits,
|
|
4357
|
+
type: Type.DEBT_OF,
|
|
4358
|
+
asset: viem.zeroAddress,
|
|
4359
|
+
blockNumber
|
|
4360
|
+
}));
|
|
4361
|
+
continue;
|
|
4362
|
+
}
|
|
4363
|
+
if (eventName === repayEvent.name) {
|
|
4364
|
+
const args = rawLog.args;
|
|
4365
|
+
if (args?.id === void 0 || args?.obligationUnits === void 0 || args?.onBehalf === void 0) {
|
|
4366
|
+
logger.debug({
|
|
4367
|
+
chainId,
|
|
4368
|
+
msg: "Skipping Repay log because it is missing required args"
|
|
4369
|
+
});
|
|
4370
|
+
continue;
|
|
4371
|
+
}
|
|
4372
|
+
if (args.obligationUnits === 0n) continue;
|
|
4373
|
+
transfers.push(from$9({
|
|
4374
|
+
id: `${baseId}-debt-repay`,
|
|
4375
|
+
chainId,
|
|
4376
|
+
contract: args.id,
|
|
4377
|
+
from: viem.zeroAddress,
|
|
4378
|
+
to: args.onBehalf,
|
|
4379
|
+
value: args.obligationUnits,
|
|
4380
|
+
type: Type.DEBT_OF,
|
|
4381
|
+
asset: viem.zeroAddress,
|
|
4382
|
+
blockNumber: Number(rawLog.blockNumber)
|
|
4383
|
+
}));
|
|
4384
|
+
continue;
|
|
4385
|
+
}
|
|
4386
|
+
if (eventName === liquidateEvent.name) {
|
|
4387
|
+
const args = rawLog.args;
|
|
4388
|
+
if (args?.id === void 0 || args?.borrower === void 0 || args?.totalRepaid === void 0 || args?.badDebt === void 0) {
|
|
4389
|
+
logger.debug({
|
|
4390
|
+
chainId,
|
|
4391
|
+
msg: "Skipping Liquidate log because it is missing required args"
|
|
4392
|
+
});
|
|
4393
|
+
continue;
|
|
4394
|
+
}
|
|
4395
|
+
const totalReduction = args.totalRepaid + args.badDebt;
|
|
4396
|
+
if (totalReduction === 0n) continue;
|
|
4397
|
+
transfers.push(from$9({
|
|
4398
|
+
id: `${baseId}-debt-liquidate`,
|
|
4399
|
+
chainId,
|
|
4400
|
+
contract: args.id,
|
|
4401
|
+
from: viem.zeroAddress,
|
|
4402
|
+
to: args.borrower,
|
|
4403
|
+
value: totalReduction,
|
|
4404
|
+
type: Type.DEBT_OF,
|
|
4405
|
+
asset: viem.zeroAddress,
|
|
4406
|
+
blockNumber: Number(rawLog.blockNumber)
|
|
4407
|
+
}));
|
|
4408
|
+
}
|
|
4409
|
+
}
|
|
4410
|
+
return transfers;
|
|
4411
|
+
}
|
|
4412
|
+
|
|
4413
|
+
//#endregion
|
|
4414
|
+
//#region src/indexer/collectors/CollectFunctions/collectMorphoV2.ts
|
|
4415
|
+
async function* collectMorphoV2(parameters) {
|
|
3925
4416
|
let { db, collector, client, lastBlockNumber: blockNumber, epoch, options: { maxBatchSize = 1e3, blockWindow } = {} } = parameters;
|
|
3926
4417
|
const logger = getLogger();
|
|
3927
4418
|
let startBlock = blockNumber;
|
|
@@ -3940,179 +4431,63 @@ async function* collectConsumedEvents(parameters) {
|
|
|
3940
4431
|
});
|
|
3941
4432
|
for await (const { logs, blockNumber: lastStreamBlockNumber } of stream) {
|
|
3942
4433
|
const parsedLogs = (0, viem.parseEventLogs)({
|
|
3943
|
-
abi: [
|
|
4434
|
+
abi: [
|
|
4435
|
+
consumedEvent,
|
|
4436
|
+
takeEvent,
|
|
4437
|
+
repayEvent,
|
|
4438
|
+
liquidateEvent,
|
|
4439
|
+
supplyCollateralEvent,
|
|
4440
|
+
withdrawCollateralEvent
|
|
4441
|
+
],
|
|
3944
4442
|
logs,
|
|
3945
4443
|
strict: false
|
|
3946
4444
|
});
|
|
3947
|
-
const
|
|
3948
|
-
|
|
3949
|
-
|
|
3950
|
-
|
|
3951
|
-
|
|
3952
|
-
|
|
3953
|
-
|
|
3954
|
-
|
|
3955
|
-
|
|
3956
|
-
|
|
3957
|
-
|
|
3958
|
-
|
|
3959
|
-
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
};
|
|
3964
|
-
for (const rawLog of parsedLogs) {
|
|
3965
|
-
if (rawLog.blockNumber === null || rawLog.logIndex === null || rawLog.transactionHash === null) {
|
|
3966
|
-
logger.debug({
|
|
3967
|
-
collector,
|
|
3968
|
-
chainId: client.chain.id,
|
|
3969
|
-
msg: "Skipping log because it is missing required fields"
|
|
3970
|
-
});
|
|
3971
|
-
continue;
|
|
3972
|
-
}
|
|
3973
|
-
if (rawLog.eventName === consumedEvent.name) {
|
|
3974
|
-
const consumeArgs = rawLog.args;
|
|
3975
|
-
if (consumeArgs.user === void 0 || consumeArgs.group === void 0 || consumeArgs.amount === void 0) {
|
|
3976
|
-
logger.debug({
|
|
3977
|
-
collector,
|
|
3978
|
-
chainId: client.chain.id,
|
|
3979
|
-
msg: "Skipping Consume log because it is missing required args"
|
|
3980
|
-
});
|
|
3981
|
-
continue;
|
|
3982
|
-
}
|
|
3983
|
-
recordLog({
|
|
3984
|
-
kind: "consume",
|
|
3985
|
-
id: `${rawLog.blockNumber.toString()}-${rawLog.logIndex.toString()}-${client.chain.id}-${rawLog.transactionHash}`,
|
|
3986
|
-
chainId: client.chain.id,
|
|
3987
|
-
maker: consumeArgs.user,
|
|
3988
|
-
group: consumeArgs.group,
|
|
3989
|
-
amount: consumeArgs.amount,
|
|
3990
|
-
blockNumber: Number(rawLog.blockNumber)
|
|
3991
|
-
});
|
|
3992
|
-
continue;
|
|
3993
|
-
}
|
|
3994
|
-
if (rawLog.eventName === takeEvent.name) {
|
|
3995
|
-
const takeArgs = rawLog.args;
|
|
3996
|
-
if (takeArgs.maker === void 0 || takeArgs.group === void 0 || takeArgs.consumed === void 0) {
|
|
3997
|
-
logger.debug({
|
|
3998
|
-
collector,
|
|
3999
|
-
chainId: client.chain.id,
|
|
4000
|
-
msg: "Skipping Take log because it is missing required args"
|
|
4001
|
-
});
|
|
4002
|
-
continue;
|
|
4003
|
-
}
|
|
4004
|
-
recordLog({
|
|
4005
|
-
kind: "take",
|
|
4006
|
-
id: `${rawLog.blockNumber.toString()}-${rawLog.logIndex.toString()}-${client.chain.id}-${rawLog.transactionHash}`,
|
|
4007
|
-
chainId: client.chain.id,
|
|
4008
|
-
maker: takeArgs.maker,
|
|
4009
|
-
group: takeArgs.group,
|
|
4010
|
-
consumed: takeArgs.consumed,
|
|
4011
|
-
blockNumber: Number(rawLog.blockNumber)
|
|
4012
|
-
});
|
|
4013
|
-
}
|
|
4014
|
-
}
|
|
4445
|
+
const consumedEvents = processConsumedLogs({
|
|
4446
|
+
logs: parsedLogs,
|
|
4447
|
+
chainId: client.chain.id
|
|
4448
|
+
});
|
|
4449
|
+
const debtTransfers = processDebtTransfers({
|
|
4450
|
+
logs: parsedLogs,
|
|
4451
|
+
chainId: client.chain.id
|
|
4452
|
+
});
|
|
4453
|
+
const collateralTransfers = processCollateralTransfers({
|
|
4454
|
+
logs: parsedLogs,
|
|
4455
|
+
chainId: client.chain.id
|
|
4456
|
+
});
|
|
4457
|
+
const seizureEvents = processCollateralSeizures({
|
|
4458
|
+
logs: parsedLogs,
|
|
4459
|
+
chainId: client.chain.id
|
|
4460
|
+
});
|
|
4015
4461
|
await db.transaction(async (dbTx) => {
|
|
4016
|
-
const
|
|
4017
|
-
|
|
4018
|
-
|
|
4019
|
-
|
|
4020
|
-
|
|
4021
|
-
|
|
4022
|
-
|
|
4023
|
-
|
|
4024
|
-
|
|
4025
|
-
|
|
4026
|
-
|
|
4027
|
-
|
|
4028
|
-
|
|
4029
|
-
const consumedByGroup = /* @__PURE__ */ new Map();
|
|
4030
|
-
if (groups$3.size > 0) {
|
|
4031
|
-
const groupList = Array.from(groups$3.values());
|
|
4032
|
-
for (let index = 0; index < groupList.length; index += 500) {
|
|
4033
|
-
const slice = groupList.slice(index, index + 500);
|
|
4034
|
-
const { rows } = await dbTx.execute(drizzle_orm.sql`
|
|
4035
|
-
WITH targets(chain_id, maker, "group") AS (
|
|
4036
|
-
VALUES ${drizzle_orm.sql.join(slice.map((group) => drizzle_orm.sql`(${group.chainId}::bigint, ${group.maker.toLowerCase()}::varchar(42), ${group.group.toLowerCase()}::varchar(66))`), drizzle_orm.sql`,`)}
|
|
4037
|
-
)
|
|
4038
|
-
SELECT
|
|
4039
|
-
targets.chain_id,
|
|
4040
|
-
targets.maker,
|
|
4041
|
-
targets."group",
|
|
4042
|
-
COALESCE(g.consumed, 0)::numeric AS consumed
|
|
4043
|
-
FROM targets
|
|
4044
|
-
LEFT JOIN ${groups} g
|
|
4045
|
-
ON g.chain_id = targets.chain_id
|
|
4046
|
-
AND g.maker = targets.maker
|
|
4047
|
-
AND g."group" = targets."group";
|
|
4048
|
-
`);
|
|
4049
|
-
for (const row of rows) {
|
|
4050
|
-
const groupKey = buildGroupKey({
|
|
4051
|
-
chainId: Number(row.chain_id),
|
|
4052
|
-
maker: row.maker,
|
|
4053
|
-
group: row.group
|
|
4054
|
-
});
|
|
4055
|
-
consumedByGroup.set(groupKey, BigInt(row.consumed ?? "0"));
|
|
4056
|
-
}
|
|
4057
|
-
}
|
|
4058
|
-
}
|
|
4059
|
-
const events = [];
|
|
4060
|
-
for (const log of normalizedLogs) {
|
|
4061
|
-
if (existingEventIds.has(log.id)) continue;
|
|
4062
|
-
const groupKey = buildGroupKey({
|
|
4063
|
-
chainId: log.chainId,
|
|
4064
|
-
maker: log.maker,
|
|
4065
|
-
group: log.group
|
|
4066
|
-
});
|
|
4067
|
-
const previousConsumed = consumedByGroup.get(groupKey) ?? 0n;
|
|
4068
|
-
if (log.kind === "consume") {
|
|
4069
|
-
events.push({
|
|
4070
|
-
id: log.id,
|
|
4071
|
-
chainId: log.chainId,
|
|
4072
|
-
maker: log.maker,
|
|
4073
|
-
group: log.group,
|
|
4074
|
-
amount: log.amount,
|
|
4075
|
-
blockNumber: log.blockNumber
|
|
4076
|
-
});
|
|
4077
|
-
consumedByGroup.set(groupKey, previousConsumed + log.amount);
|
|
4078
|
-
continue;
|
|
4079
|
-
}
|
|
4080
|
-
const delta = log.consumed - previousConsumed;
|
|
4081
|
-
if (delta <= 0n) {
|
|
4082
|
-
logger.debug({
|
|
4083
|
-
collector,
|
|
4084
|
-
chainId: client.chain.id,
|
|
4085
|
-
msg: "Skipping Take log because consumed did not increase",
|
|
4086
|
-
previous_consumed: previousConsumed.toString(),
|
|
4087
|
-
consumed: log.consumed.toString()
|
|
4088
|
-
});
|
|
4089
|
-
continue;
|
|
4090
|
-
}
|
|
4091
|
-
events.push({
|
|
4092
|
-
id: log.id,
|
|
4093
|
-
chainId: log.chainId,
|
|
4094
|
-
maker: log.maker,
|
|
4095
|
-
group: log.group,
|
|
4096
|
-
amount: delta,
|
|
4097
|
-
blockNumber: log.blockNumber
|
|
4098
|
-
});
|
|
4099
|
-
consumedByGroup.set(groupKey, log.consumed);
|
|
4462
|
+
const [resolvedSeizureTransfers, resolvedConsumedEvents] = await Promise.all([resolveSeizureTransfers({
|
|
4463
|
+
dbTx,
|
|
4464
|
+
seizureEvents
|
|
4465
|
+
}), resolveConsumedEvents({
|
|
4466
|
+
dbTx,
|
|
4467
|
+
consumedEvents,
|
|
4468
|
+
chainId: client.chain.id,
|
|
4469
|
+
collector,
|
|
4470
|
+
logger
|
|
4471
|
+
})]);
|
|
4472
|
+
if (debtTransfers.length > 0) {
|
|
4473
|
+
await dbTx.positions.upsert(transfersToPositions(debtTransfers));
|
|
4474
|
+
await dbTx.transfers.create(debtTransfers);
|
|
4100
4475
|
}
|
|
4101
|
-
|
|
4102
|
-
|
|
4103
|
-
|
|
4104
|
-
|
|
4105
|
-
collector,
|
|
4106
|
-
count: events.length,
|
|
4107
|
-
chain_id: client.chain.id,
|
|
4108
|
-
block_range: [startBlock, lastStreamBlockNumber]
|
|
4109
|
-
});
|
|
4110
|
-
} catch (err) {
|
|
4111
|
-
logger.error({
|
|
4112
|
-
err,
|
|
4113
|
-
msg: "Failed to process consumed events"
|
|
4114
|
-
});
|
|
4476
|
+
const allCollateralTransfers = [...resolvedSeizureTransfers, ...collateralTransfers];
|
|
4477
|
+
if (allCollateralTransfers.length > 0) {
|
|
4478
|
+
await dbTx.positions.upsert(transfersToPositions(allCollateralTransfers));
|
|
4479
|
+
await dbTx.transfers.create(allCollateralTransfers);
|
|
4115
4480
|
}
|
|
4481
|
+
await dbTx.consumed.create(resolvedConsumedEvents);
|
|
4482
|
+
if (resolvedConsumedEvents.length > 0) logger.info({
|
|
4483
|
+
msg: "Events indexed",
|
|
4484
|
+
collector,
|
|
4485
|
+
consumed_count: resolvedConsumedEvents.length,
|
|
4486
|
+
debt_transfer_count: debtTransfers.length,
|
|
4487
|
+
collateral_transfer_count: allCollateralTransfers.length,
|
|
4488
|
+
chain_id: client.chain.id,
|
|
4489
|
+
block_range: [startBlock, lastStreamBlockNumber]
|
|
4490
|
+
});
|
|
4116
4491
|
blockNumber = lastStreamBlockNumber;
|
|
4117
4492
|
try {
|
|
4118
4493
|
await dbTx.blocks.advanceCollector({
|
|
@@ -4128,15 +4503,27 @@ async function* collectConsumedEvents(parameters) {
|
|
|
4128
4503
|
chainId: client.chain.id
|
|
4129
4504
|
});
|
|
4130
4505
|
blockNumber = ancestor.blockNumber;
|
|
4131
|
-
const
|
|
4506
|
+
const deletedConsumed = await dbTx.consumed.delete({
|
|
4132
4507
|
chainId: client.chain.id,
|
|
4133
4508
|
blockNumberGte: blockNumber + 1
|
|
4134
4509
|
});
|
|
4510
|
+
const deletedDebtTransfers = await dbTx.transfers.delete({
|
|
4511
|
+
chainId: client.chain.id,
|
|
4512
|
+
blockNumberGte: blockNumber + 1,
|
|
4513
|
+
positionTypeId: positionTypeId(Type.DEBT_OF)
|
|
4514
|
+
});
|
|
4515
|
+
const deletedCollateralTransfers = await dbTx.transfers.delete({
|
|
4516
|
+
chainId: client.chain.id,
|
|
4517
|
+
blockNumberGte: blockNumber + 1,
|
|
4518
|
+
positionTypeId: positionTypeId(Type.COLLATERAL_OF)
|
|
4519
|
+
});
|
|
4135
4520
|
logger.info({
|
|
4136
4521
|
collector,
|
|
4137
4522
|
chain_id: client.chain.id,
|
|
4138
|
-
msg:
|
|
4139
|
-
|
|
4523
|
+
msg: "Reorg detected, events deleted",
|
|
4524
|
+
consumed_deleted: deletedConsumed,
|
|
4525
|
+
debt_transfers_deleted: deletedDebtTransfers,
|
|
4526
|
+
collateral_transfers_deleted: deletedCollateralTransfers,
|
|
4140
4527
|
block_number: blockNumber
|
|
4141
4528
|
});
|
|
4142
4529
|
await dbTx.blocks.advanceCollector({
|
|
@@ -4147,7 +4534,7 @@ async function* collectConsumedEvents(parameters) {
|
|
|
4147
4534
|
});
|
|
4148
4535
|
reorgDetected = true;
|
|
4149
4536
|
} catch (err) {
|
|
4150
|
-
const msg = "Failed to delete
|
|
4537
|
+
const msg = "Failed to delete events when handling reorg.";
|
|
4151
4538
|
logger.error({
|
|
4152
4539
|
collector,
|
|
4153
4540
|
chainId: client.chain.id,
|
|
@@ -4162,10 +4549,210 @@ async function* collectConsumedEvents(parameters) {
|
|
|
4162
4549
|
yield blockNumber;
|
|
4163
4550
|
startBlock = blockNumber;
|
|
4164
4551
|
}
|
|
4552
|
+
if (!reorgDetected) await db.transaction(async (dbTx) => {
|
|
4553
|
+
const collectorState = await dbTx.blocks.getCollector({
|
|
4554
|
+
collectorName: collector,
|
|
4555
|
+
chainId: client.chain.id
|
|
4556
|
+
});
|
|
4557
|
+
const deletedConsumed = await dbTx.consumed.delete({
|
|
4558
|
+
chainId: client.chain.id,
|
|
4559
|
+
blockNumberGte: collectorState.blockNumber + 1
|
|
4560
|
+
});
|
|
4561
|
+
const deletedDebtTransfers = await dbTx.transfers.delete({
|
|
4562
|
+
chainId: client.chain.id,
|
|
4563
|
+
blockNumberGte: collectorState.blockNumber + 1,
|
|
4564
|
+
positionTypeId: positionTypeId(Type.DEBT_OF)
|
|
4565
|
+
});
|
|
4566
|
+
const deletedCollateralTransfers = await dbTx.transfers.delete({
|
|
4567
|
+
chainId: client.chain.id,
|
|
4568
|
+
blockNumberGte: collectorState.blockNumber + 1,
|
|
4569
|
+
positionTypeId: positionTypeId(Type.COLLATERAL_OF)
|
|
4570
|
+
});
|
|
4571
|
+
if (deletedConsumed > 0 || deletedDebtTransfers > 0 || deletedCollateralTransfers > 0) logger.info({
|
|
4572
|
+
collector,
|
|
4573
|
+
chain_id: client.chain.id,
|
|
4574
|
+
msg: "Reorg detected, events deleted",
|
|
4575
|
+
consumed_deleted: deletedConsumed,
|
|
4576
|
+
debt_transfers_deleted: deletedDebtTransfers,
|
|
4577
|
+
collateral_transfers_deleted: deletedCollateralTransfers,
|
|
4578
|
+
block_number: collectorState.blockNumber
|
|
4579
|
+
});
|
|
4580
|
+
});
|
|
4581
|
+
}
|
|
4582
|
+
async function resolveSeizureTransfers(parameters) {
|
|
4583
|
+
const { dbTx, seizureEvents } = parameters;
|
|
4584
|
+
if (seizureEvents.length === 0) return [];
|
|
4585
|
+
const uniqueObligationIds = [...new Set(seizureEvents.map((event) => event.obligationId.toLowerCase()))];
|
|
4586
|
+
const rows = await dbTx.select({
|
|
4587
|
+
obligationId: obligationIdKeys.obligationId,
|
|
4588
|
+
collateralIndex: obligationCollateralsV2.collateralIndex,
|
|
4589
|
+
asset: obligationCollateralsV2.asset
|
|
4590
|
+
}).from(obligationIdKeys).innerJoin(obligationCollateralsV2, (0, drizzle_orm.eq)(obligationIdKeys.obligationKey, obligationCollateralsV2.obligationKey)).where((0, drizzle_orm.inArray)(obligationIdKeys.obligationId, uniqueObligationIds));
|
|
4591
|
+
const resolutionMap = /* @__PURE__ */ new Map();
|
|
4592
|
+
for (const row of rows) resolutionMap.set(`${row.obligationId.toLowerCase()}-${row.collateralIndex}`, row.asset);
|
|
4593
|
+
const resolvedSeizureTransfers = [];
|
|
4594
|
+
for (const seizure of seizureEvents) {
|
|
4595
|
+
const key = `${seizure.obligationId.toLowerCase()}-${seizure.collateralIndex}`;
|
|
4596
|
+
const asset = resolutionMap.get(key);
|
|
4597
|
+
if (asset === void 0) throw new Error(`Unresolvable Liquidate seizure: obligationId=${seizure.obligationId}, collateralIndex=${seizure.collateralIndex}, chainId=${seizure.chainId}, blockNumber=${seizure.blockNumber}`);
|
|
4598
|
+
resolvedSeizureTransfers.push(from$9({
|
|
4599
|
+
id: seizure.id,
|
|
4600
|
+
chainId: seizure.chainId,
|
|
4601
|
+
contract: seizure.obligationId,
|
|
4602
|
+
from: seizure.user,
|
|
4603
|
+
to: viem.zeroAddress,
|
|
4604
|
+
value: seizure.amount,
|
|
4605
|
+
type: Type.COLLATERAL_OF,
|
|
4606
|
+
asset,
|
|
4607
|
+
blockNumber: seizure.blockNumber
|
|
4608
|
+
}));
|
|
4609
|
+
}
|
|
4610
|
+
return resolvedSeizureTransfers;
|
|
4611
|
+
}
|
|
4612
|
+
async function resolveConsumedEvents(parameters) {
|
|
4613
|
+
const { dbTx, consumedEvents, chainId, collector, logger } = parameters;
|
|
4614
|
+
if (consumedEvents.length === 0) return [];
|
|
4615
|
+
const [existingConsumedIds, consumedByGroup] = await Promise.all([getExistingConsumedIds({
|
|
4616
|
+
dbTx,
|
|
4617
|
+
consumedEvents
|
|
4618
|
+
}), getConsumedByGroup({
|
|
4619
|
+
dbTx,
|
|
4620
|
+
consumedEvents
|
|
4621
|
+
})]);
|
|
4622
|
+
const resolvedEvents = [];
|
|
4623
|
+
for (const log of consumedEvents) {
|
|
4624
|
+
if (existingConsumedIds.has(log.id)) continue;
|
|
4625
|
+
const groupKey = buildGroupKey({
|
|
4626
|
+
chainId: log.chainId,
|
|
4627
|
+
maker: log.maker,
|
|
4628
|
+
group: log.group
|
|
4629
|
+
});
|
|
4630
|
+
const previousConsumed = consumedByGroup.get(groupKey) ?? 0n;
|
|
4631
|
+
if (log.kind === "consume") {
|
|
4632
|
+
resolvedEvents.push({
|
|
4633
|
+
id: log.id,
|
|
4634
|
+
chainId: log.chainId,
|
|
4635
|
+
maker: log.maker,
|
|
4636
|
+
group: log.group,
|
|
4637
|
+
amount: log.amount,
|
|
4638
|
+
blockNumber: log.blockNumber
|
|
4639
|
+
});
|
|
4640
|
+
consumedByGroup.set(groupKey, previousConsumed + log.amount);
|
|
4641
|
+
continue;
|
|
4642
|
+
}
|
|
4643
|
+
const delta = log.consumed - previousConsumed;
|
|
4644
|
+
if (delta <= 0n) {
|
|
4645
|
+
logger.debug({
|
|
4646
|
+
collector,
|
|
4647
|
+
chainId,
|
|
4648
|
+
msg: "Skipping Take log because consumed did not increase",
|
|
4649
|
+
previous_consumed: previousConsumed.toString(),
|
|
4650
|
+
consumed: log.consumed.toString()
|
|
4651
|
+
});
|
|
4652
|
+
continue;
|
|
4653
|
+
}
|
|
4654
|
+
resolvedEvents.push({
|
|
4655
|
+
id: log.id,
|
|
4656
|
+
chainId: log.chainId,
|
|
4657
|
+
maker: log.maker,
|
|
4658
|
+
group: log.group,
|
|
4659
|
+
amount: delta,
|
|
4660
|
+
blockNumber: log.blockNumber
|
|
4661
|
+
});
|
|
4662
|
+
consumedByGroup.set(groupKey, log.consumed);
|
|
4663
|
+
}
|
|
4664
|
+
return resolvedEvents;
|
|
4665
|
+
}
|
|
4666
|
+
async function getExistingConsumedIds(parameters) {
|
|
4667
|
+
const { dbTx, consumedEvents: consumedEvents$1 } = parameters;
|
|
4668
|
+
const existingConsumedIds = /* @__PURE__ */ new Set();
|
|
4669
|
+
const ids = Array.from(new Set(consumedEvents$1.map((event) => event.id)));
|
|
4670
|
+
for (let index = 0; index < ids.length; index += 500) {
|
|
4671
|
+
const slice = ids.slice(index, index + 500);
|
|
4672
|
+
const { rows } = await dbTx.execute(drizzle_orm.sql`
|
|
4673
|
+
SELECT event_id
|
|
4674
|
+
FROM ${consumedEvents}
|
|
4675
|
+
WHERE event_id IN (${drizzle_orm.sql.join(slice.map((id) => drizzle_orm.sql`${id}`), drizzle_orm.sql`,`)});
|
|
4676
|
+
`);
|
|
4677
|
+
for (const row of rows) existingConsumedIds.add(row.event_id);
|
|
4678
|
+
}
|
|
4679
|
+
return existingConsumedIds;
|
|
4680
|
+
}
|
|
4681
|
+
async function getConsumedByGroup(parameters) {
|
|
4682
|
+
const { dbTx, consumedEvents } = parameters;
|
|
4683
|
+
const groups$3 = /* @__PURE__ */ new Map();
|
|
4684
|
+
for (const event of consumedEvents) {
|
|
4685
|
+
const key = buildGroupKey({
|
|
4686
|
+
chainId: event.chainId,
|
|
4687
|
+
maker: event.maker,
|
|
4688
|
+
group: event.group
|
|
4689
|
+
});
|
|
4690
|
+
if (!groups$3.has(key)) groups$3.set(key, {
|
|
4691
|
+
chainId: event.chainId,
|
|
4692
|
+
maker: event.maker,
|
|
4693
|
+
group: event.group
|
|
4694
|
+
});
|
|
4695
|
+
}
|
|
4696
|
+
const consumedByGroup = /* @__PURE__ */ new Map();
|
|
4697
|
+
const groupList = Array.from(groups$3.values());
|
|
4698
|
+
for (let index = 0; index < groupList.length; index += 500) {
|
|
4699
|
+
const slice = groupList.slice(index, index + 500);
|
|
4700
|
+
const { rows } = await dbTx.execute(drizzle_orm.sql`
|
|
4701
|
+
WITH targets(chain_id, maker, "group") AS (
|
|
4702
|
+
VALUES ${drizzle_orm.sql.join(slice.map((group) => drizzle_orm.sql`(${group.chainId}::bigint, ${group.maker.toLowerCase()}::varchar(42), ${group.group.toLowerCase()}::varchar(66))`), drizzle_orm.sql`,`)}
|
|
4703
|
+
)
|
|
4704
|
+
SELECT
|
|
4705
|
+
targets.chain_id,
|
|
4706
|
+
targets.maker,
|
|
4707
|
+
targets."group",
|
|
4708
|
+
COALESCE(g.consumed, 0)::numeric AS consumed
|
|
4709
|
+
FROM targets
|
|
4710
|
+
LEFT JOIN ${groups} g
|
|
4711
|
+
ON g.chain_id = targets.chain_id
|
|
4712
|
+
AND g.maker = targets.maker
|
|
4713
|
+
AND g."group" = targets."group";
|
|
4714
|
+
`);
|
|
4715
|
+
for (const row of rows) {
|
|
4716
|
+
const groupKey = buildGroupKey({
|
|
4717
|
+
chainId: Number(row.chain_id),
|
|
4718
|
+
maker: row.maker,
|
|
4719
|
+
group: row.group
|
|
4720
|
+
});
|
|
4721
|
+
consumedByGroup.set(groupKey, BigInt(row.consumed ?? "0"));
|
|
4722
|
+
}
|
|
4723
|
+
}
|
|
4724
|
+
return consumedByGroup;
|
|
4725
|
+
}
|
|
4726
|
+
function transfersToPositions(transfers) {
|
|
4727
|
+
if (transfers.length === 0) return [];
|
|
4728
|
+
const transferType = transfers[0].type;
|
|
4729
|
+
if (transfers.some((transfer) => transfer.type !== transferType)) throw new Error("Cannot map transfers with mixed position types to positions.");
|
|
4730
|
+
const positionKeys = /* @__PURE__ */ new Map();
|
|
4731
|
+
for (const transfer of transfers) for (const user of [transfer.from, transfer.to]) {
|
|
4732
|
+
const key = `${transfer.chainId}-${transfer.contract}-${user}-${transfer.asset}`.toLowerCase();
|
|
4733
|
+
const existing = positionKeys.get(key);
|
|
4734
|
+
if (!existing || transfer.blockNumber < existing.blockNumber) positionKeys.set(key, {
|
|
4735
|
+
chainId: transfer.chainId,
|
|
4736
|
+
contract: transfer.contract,
|
|
4737
|
+
user,
|
|
4738
|
+
asset: transfer.asset,
|
|
4739
|
+
blockNumber: transfer.blockNumber
|
|
4740
|
+
});
|
|
4741
|
+
}
|
|
4742
|
+
return Array.from(positionKeys.values()).map((position) => from$12({
|
|
4743
|
+
chainId: position.chainId,
|
|
4744
|
+
contract: position.contract,
|
|
4745
|
+
user: position.user,
|
|
4746
|
+
type: transferType,
|
|
4747
|
+
balance: 0n,
|
|
4748
|
+
asset: position.asset,
|
|
4749
|
+
blockNumber: position.blockNumber
|
|
4750
|
+
}));
|
|
4165
4751
|
}
|
|
4166
4752
|
|
|
4167
4753
|
//#endregion
|
|
4168
4754
|
//#region src/indexer/collectors/CollectFunctions/collectOffers.ts
|
|
4755
|
+
const ERC20_TYPE_ID = Object.values(Type).indexOf(Type.ERC20) + 1;
|
|
4169
4756
|
async function* collectOffersV2(parameters) {
|
|
4170
4757
|
let { db, collector, client, lastBlockNumber: blockNumber, gatekeeper, options: { maxBatchSize = 1e3, blockWindow } = {} } = parameters;
|
|
4171
4758
|
const logger = getLogger();
|
|
@@ -4179,9 +4766,10 @@ async function* collectOffersV2(parameters) {
|
|
|
4179
4766
|
});
|
|
4180
4767
|
throw new Error(msg);
|
|
4181
4768
|
}
|
|
4769
|
+
const morphoV2 = client.chain.custom.morpho.address;
|
|
4182
4770
|
const signatureDomain = {
|
|
4183
4771
|
chainId: client.chain.id,
|
|
4184
|
-
verifyingContract:
|
|
4772
|
+
verifyingContract: morphoV2
|
|
4185
4773
|
};
|
|
4186
4774
|
const { blockNumber: latestBlockNumberChain } = await db.blocks.getChain(client.chain.id);
|
|
4187
4775
|
const stream = streamLogs({
|
|
@@ -4244,10 +4832,14 @@ async function* collectOffersV2(parameters) {
|
|
|
4244
4832
|
await db.transaction(async (dbTx) => {
|
|
4245
4833
|
const { epoch, blockNumber: latestBlockNumber } = await dbTx.blocks.getChain(client.chain.id);
|
|
4246
4834
|
const treesToInsert = [];
|
|
4835
|
+
const pathsToInsert = [];
|
|
4247
4836
|
let totalValidOffers = 0;
|
|
4248
4837
|
const offersWithBlock = [];
|
|
4249
4838
|
for (const { tree, signature, blockNumber: treeBlockNumber } of decodedTrees) try {
|
|
4250
|
-
const allowedResults = await gatekeeper.isAllowed(
|
|
4839
|
+
const allowedResults = await gatekeeper.isAllowed({
|
|
4840
|
+
offers: tree.offers,
|
|
4841
|
+
chainId: client.chain.id
|
|
4842
|
+
});
|
|
4251
4843
|
const hasBlockWindowViolation = treeBlockNumber > latestBlockNumber;
|
|
4252
4844
|
if (!(allowedResults.issues.length === 0 && allowedResults.valid.length === tree.offers.length) || hasBlockWindowViolation) {
|
|
4253
4845
|
if (allowedResults.issues.length > 0) {
|
|
@@ -4266,14 +4858,35 @@ async function* collectOffersV2(parameters) {
|
|
|
4266
4858
|
continue;
|
|
4267
4859
|
}
|
|
4268
4860
|
treesToInsert.push({
|
|
4269
|
-
tree,
|
|
4861
|
+
root: tree.root,
|
|
4270
4862
|
signature
|
|
4271
4863
|
});
|
|
4272
4864
|
totalValidOffers += tree.offers.length;
|
|
4273
|
-
|
|
4274
|
-
|
|
4275
|
-
|
|
4276
|
-
|
|
4865
|
+
const obligationIdsByOfferHash = /* @__PURE__ */ new Map();
|
|
4866
|
+
for (const offer of tree.offers) {
|
|
4867
|
+
const offerHash = hash(offer).toLowerCase();
|
|
4868
|
+
const obligationId$1 = obligationId(offer, {
|
|
4869
|
+
chainId: client.chain.id,
|
|
4870
|
+
morphoV2
|
|
4871
|
+
}).toLowerCase();
|
|
4872
|
+
offersWithBlock.push({
|
|
4873
|
+
offer,
|
|
4874
|
+
blockNumber: treeBlockNumber,
|
|
4875
|
+
obligationId: obligationId$1
|
|
4876
|
+
});
|
|
4877
|
+
obligationIdsByOfferHash.set(offerHash, obligationId$1);
|
|
4878
|
+
}
|
|
4879
|
+
for (const proof of proofs(tree)) {
|
|
4880
|
+
const offerHash = hash(proof.offer).toLowerCase();
|
|
4881
|
+
const obligationId = obligationIdsByOfferHash.get(offerHash);
|
|
4882
|
+
if (obligationId === void 0) continue;
|
|
4883
|
+
pathsToInsert.push({
|
|
4884
|
+
offerHash,
|
|
4885
|
+
obligationId,
|
|
4886
|
+
treeRoot: tree.root,
|
|
4887
|
+
proof: proof.path
|
|
4888
|
+
});
|
|
4889
|
+
}
|
|
4277
4890
|
} catch (err) {
|
|
4278
4891
|
const error = err instanceof Error ? err : new Error(String(err));
|
|
4279
4892
|
logger.error({
|
|
@@ -4283,19 +4896,23 @@ async function* collectOffersV2(parameters) {
|
|
|
4283
4896
|
});
|
|
4284
4897
|
throw new Error("Gatekeeper validation failed", { cause: error });
|
|
4285
4898
|
}
|
|
4286
|
-
const dependencies = buildOfferDependencies(
|
|
4899
|
+
const dependencies = buildOfferDependencies({
|
|
4900
|
+
offers: offersWithBlock,
|
|
4901
|
+
chainId: client.chain.id,
|
|
4902
|
+
morphoV2
|
|
4903
|
+
});
|
|
4287
4904
|
await dbTx.oracles.upsert(dependencies.oracles);
|
|
4288
4905
|
await dbTx.obligations.create(dependencies.obligations);
|
|
4289
4906
|
await dbTx.groups.create(dependencies.groups);
|
|
4290
|
-
const
|
|
4291
|
-
if (treesToInsert.length > 0) await dbTx.trees.
|
|
4292
|
-
|
|
4293
|
-
offers: offersWithBlock,
|
|
4294
|
-
hashes: insertedHashes
|
|
4295
|
-
});
|
|
4907
|
+
const insertedReferences = await dbTx.offers.create(dependencies.offerBatches);
|
|
4908
|
+
if (treesToInsert.length > 0) await dbTx.trees.upsert(treesToInsert);
|
|
4909
|
+
if (pathsToInsert.length > 0) await dbTx.trees.upsertPaths(pathsToInsert);
|
|
4296
4910
|
const { callbacks, positions, lots } = decodeCallbacks({
|
|
4297
|
-
|
|
4298
|
-
|
|
4911
|
+
offers: filterInsertedOffers({
|
|
4912
|
+
offers: offersWithBlock,
|
|
4913
|
+
references: insertedReferences
|
|
4914
|
+
}),
|
|
4915
|
+
chainId: client.chain.id
|
|
4299
4916
|
});
|
|
4300
4917
|
if (positions.length > 0) await dbTx.positions.upsert(positions);
|
|
4301
4918
|
if (callbacks.length > 0) await dbTx.callbacks.upsert(callbacks);
|
|
@@ -4358,7 +4975,7 @@ async function* collectOffersV2(parameters) {
|
|
|
4358
4975
|
}
|
|
4359
4976
|
}
|
|
4360
4977
|
function decodeCallbacks(parameters) {
|
|
4361
|
-
const { offers } = parameters;
|
|
4978
|
+
const { offers, chainId } = parameters;
|
|
4362
4979
|
if (offers.length === 0) return {
|
|
4363
4980
|
callbacks: [],
|
|
4364
4981
|
positions: [],
|
|
@@ -4367,12 +4984,12 @@ function decodeCallbacks(parameters) {
|
|
|
4367
4984
|
const callbacks = [];
|
|
4368
4985
|
const positions = [];
|
|
4369
4986
|
const lots = [];
|
|
4370
|
-
for (const { offer, blockNumber: offerBlockNumber } of offers) {
|
|
4987
|
+
for (const { offer, blockNumber: offerBlockNumber, obligationId } of offers) {
|
|
4371
4988
|
if (!offer.buy) continue;
|
|
4372
4989
|
if (!isEmptyCallback(offer)) continue;
|
|
4373
4990
|
const loanToken = offer.loanToken.toLowerCase();
|
|
4374
4991
|
positions.push(from$12({
|
|
4375
|
-
chainId
|
|
4992
|
+
chainId,
|
|
4376
4993
|
contract: loanToken,
|
|
4377
4994
|
user: offer.maker,
|
|
4378
4995
|
type: Type.ERC20,
|
|
@@ -4380,20 +4997,23 @@ function decodeCallbacks(parameters) {
|
|
|
4380
4997
|
blockNumber: offerBlockNumber
|
|
4381
4998
|
}));
|
|
4382
4999
|
lots.push({
|
|
4383
|
-
positionChainId:
|
|
5000
|
+
positionChainId: chainId,
|
|
4384
5001
|
positionContract: loanToken,
|
|
4385
5002
|
positionUser: offer.maker,
|
|
5003
|
+
positionTypeId: ERC20_TYPE_ID,
|
|
4386
5004
|
group: offer.group,
|
|
4387
|
-
obligationId
|
|
5005
|
+
obligationId,
|
|
4388
5006
|
size: offer.assets
|
|
4389
5007
|
});
|
|
4390
5008
|
callbacks.push({
|
|
4391
5009
|
offerHash: hash(offer),
|
|
5010
|
+
obligationId,
|
|
4392
5011
|
callbacks: [{
|
|
4393
|
-
chainId
|
|
5012
|
+
chainId,
|
|
4394
5013
|
contract: loanToken,
|
|
4395
5014
|
user: offer.maker,
|
|
4396
|
-
amount: offer.assets
|
|
5015
|
+
amount: offer.assets,
|
|
5016
|
+
positionTypeId: ERC20_TYPE_ID
|
|
4397
5017
|
}]
|
|
4398
5018
|
});
|
|
4399
5019
|
}
|
|
@@ -4403,34 +5023,42 @@ function decodeCallbacks(parameters) {
|
|
|
4403
5023
|
lots
|
|
4404
5024
|
};
|
|
4405
5025
|
}
|
|
4406
|
-
function buildOfferDependencies(
|
|
5026
|
+
function buildOfferDependencies(parameters) {
|
|
5027
|
+
const { offers, chainId, morphoV2 } = parameters;
|
|
4407
5028
|
const obligationsById = /* @__PURE__ */ new Map();
|
|
4408
5029
|
const oraclesByKey = /* @__PURE__ */ new Map();
|
|
4409
5030
|
const groupsByKey = /* @__PURE__ */ new Map();
|
|
4410
5031
|
const offersByBlock = /* @__PURE__ */ new Map();
|
|
4411
|
-
for (const { offer, blockNumber } of offers) {
|
|
5032
|
+
for (const { offer, blockNumber, obligationId } of offers) {
|
|
4412
5033
|
const list = offersByBlock.get(blockNumber) ?? [];
|
|
4413
|
-
list.push(
|
|
5034
|
+
list.push({
|
|
5035
|
+
offer,
|
|
5036
|
+
obligationId,
|
|
5037
|
+
chainId
|
|
5038
|
+
});
|
|
4414
5039
|
offersByBlock.set(blockNumber, list);
|
|
4415
|
-
|
|
4416
|
-
|
|
4417
|
-
chainId
|
|
4418
|
-
|
|
4419
|
-
|
|
4420
|
-
|
|
4421
|
-
|
|
5040
|
+
if (!obligationsById.get(obligationId)) obligationsById.set(obligationId, {
|
|
5041
|
+
obligationId,
|
|
5042
|
+
chainId,
|
|
5043
|
+
morphoV2,
|
|
5044
|
+
obligation: from$15({
|
|
5045
|
+
loanToken: offer.loanToken,
|
|
5046
|
+
maturity: offer.maturity,
|
|
5047
|
+
collaterals: offer.collaterals
|
|
5048
|
+
})
|
|
5049
|
+
});
|
|
4422
5050
|
for (const collateral of offer.collaterals) {
|
|
4423
|
-
const oracleKey = `${
|
|
5051
|
+
const oracleKey = `${chainId}-${collateral.oracle}`.toLowerCase();
|
|
4424
5052
|
if (!oraclesByKey.has(oracleKey)) oraclesByKey.set(oracleKey, from$13({
|
|
4425
|
-
chainId
|
|
5053
|
+
chainId,
|
|
4426
5054
|
address: collateral.oracle,
|
|
4427
5055
|
price: null,
|
|
4428
5056
|
blockNumber
|
|
4429
5057
|
}));
|
|
4430
5058
|
}
|
|
4431
|
-
const groupKey = `${
|
|
5059
|
+
const groupKey = `${chainId}-${offer.maker}-${offer.group}`.toLowerCase();
|
|
4432
5060
|
if (!groupsByKey.has(groupKey)) groupsByKey.set(groupKey, {
|
|
4433
|
-
chainId
|
|
5061
|
+
chainId,
|
|
4434
5062
|
maker: offer.maker,
|
|
4435
5063
|
group: offer.group,
|
|
4436
5064
|
blockNumber
|
|
@@ -4447,15 +5075,22 @@ function buildOfferDependencies(offers) {
|
|
|
4447
5075
|
};
|
|
4448
5076
|
}
|
|
4449
5077
|
function filterInsertedOffers(parameters) {
|
|
4450
|
-
if (parameters.
|
|
4451
|
-
const
|
|
5078
|
+
if (parameters.references.length === 0) return [];
|
|
5079
|
+
const keyOf = (input) => `${input.hash.toLowerCase()}:${input.obligationId.toLowerCase()}`;
|
|
5080
|
+
const inserted = new Set(parameters.references.map((offer) => keyOf({
|
|
5081
|
+
hash: offer.hash,
|
|
5082
|
+
obligationId: offer.obligationId
|
|
5083
|
+
})));
|
|
4452
5084
|
const seen = /* @__PURE__ */ new Set();
|
|
4453
5085
|
const filtered = [];
|
|
4454
5086
|
for (const entry of parameters.offers) {
|
|
4455
|
-
const
|
|
4456
|
-
|
|
4457
|
-
|
|
4458
|
-
|
|
5087
|
+
const key = keyOf({
|
|
5088
|
+
hash: hash(entry.offer),
|
|
5089
|
+
obligationId: entry.obligationId
|
|
5090
|
+
});
|
|
5091
|
+
if (!inserted.has(key)) continue;
|
|
5092
|
+
if (seen.has(key)) continue;
|
|
5093
|
+
seen.add(key);
|
|
4459
5094
|
filtered.push(entry);
|
|
4460
5095
|
}
|
|
4461
5096
|
return filtered;
|
|
@@ -4570,7 +5205,7 @@ async function snapshotVaultPositions(parameters) {
|
|
|
4570
5205
|
convertToAssets: (shares) => {
|
|
4571
5206
|
const contract = contracts.get(position.contract.toLowerCase());
|
|
4572
5207
|
if (!contract) return;
|
|
4573
|
-
if (contract.decimalsOffset === void 0 || contract.totalAssets === void 0 || contract.totalSupply === void 0) return;
|
|
5208
|
+
if (contract.decimalsOffset === void 0 || contract.totalAssets === void 0 || contract.totalSupply === void 0 || contract.asset === void 0) return;
|
|
4574
5209
|
try {
|
|
4575
5210
|
position.balance = convertToAssets({
|
|
4576
5211
|
shares,
|
|
@@ -4725,12 +5360,15 @@ async function* collectPositions(parameters) {
|
|
|
4725
5360
|
from: log.args.from,
|
|
4726
5361
|
to: log.args.to,
|
|
4727
5362
|
value: log.args.value,
|
|
5363
|
+
type: Type.ERC20,
|
|
5364
|
+
asset: log.address,
|
|
4728
5365
|
blockNumber: Number(log.blockNumber)
|
|
4729
5366
|
}));
|
|
4730
5367
|
}
|
|
4731
5368
|
const { positions } = await db.positions.get({
|
|
4732
5369
|
chainId: client.chain.id,
|
|
4733
|
-
filled: false
|
|
5370
|
+
filled: false,
|
|
5371
|
+
type: Type.ERC20
|
|
4734
5372
|
});
|
|
4735
5373
|
const newPositions = [];
|
|
4736
5374
|
try {
|
|
@@ -4853,7 +5491,8 @@ async function* collectPositions(parameters) {
|
|
|
4853
5491
|
blockNumber = ancestor.blockNumber;
|
|
4854
5492
|
const emptied = await dbTx.positions.setEmptyAfter({
|
|
4855
5493
|
chainId: client.chain.id,
|
|
4856
|
-
blockNumber: blockNumber + 1
|
|
5494
|
+
blockNumber: blockNumber + 1,
|
|
5495
|
+
type: Type.ERC20
|
|
4857
5496
|
});
|
|
4858
5497
|
logger.info({
|
|
4859
5498
|
msg: "Reorg detected, positions set to empty",
|
|
@@ -5080,10 +5719,10 @@ function createBuilder(parameters) {
|
|
|
5080
5719
|
}
|
|
5081
5720
|
}));
|
|
5082
5721
|
},
|
|
5083
|
-
|
|
5084
|
-
return createCollector("
|
|
5722
|
+
buildMorphoV2Collector: ({ options: { maxBatchSize = 1e3 } = {} } = {}) => {
|
|
5723
|
+
return createCollector("morpho_v2", (p) => collectMorphoV2({
|
|
5085
5724
|
...p,
|
|
5086
|
-
collector: "
|
|
5725
|
+
collector: "morpho_v2",
|
|
5087
5726
|
options: {
|
|
5088
5727
|
maxBatchSize,
|
|
5089
5728
|
blockWindow
|
|
@@ -5132,7 +5771,7 @@ const from$7 = (parameters) => {
|
|
|
5132
5771
|
});
|
|
5133
5772
|
return {
|
|
5134
5773
|
offersCollector: collectorBuilder.buildOffersCollector({ options: { maxBatchSize } }),
|
|
5135
|
-
|
|
5774
|
+
morphoV2Collector: collectorBuilder.buildMorphoV2Collector({ options: { maxBatchSize } }),
|
|
5136
5775
|
pricesCollector: collectorBuilder.buildPricesCollector({ options: {
|
|
5137
5776
|
maxBatchSize,
|
|
5138
5777
|
retryAttempts,
|
|
@@ -5154,7 +5793,7 @@ var Indexer_exports = /* @__PURE__ */ __exportAll({
|
|
|
5154
5793
|
});
|
|
5155
5794
|
function from$6(config) {
|
|
5156
5795
|
const { client, gatekeeper, db, interval = 1e4, maxBatchSize = 1e3, maxBlockNumber, blockWindow, retryAttempts, retryDelayMs } = config;
|
|
5157
|
-
const { offersCollector,
|
|
5796
|
+
const { offersCollector, morphoV2Collector, positionsCollector, pricesCollector } = from$7({
|
|
5158
5797
|
client,
|
|
5159
5798
|
db,
|
|
5160
5799
|
gatekeeper,
|
|
@@ -5169,7 +5808,7 @@ function from$6(config) {
|
|
|
5169
5808
|
client,
|
|
5170
5809
|
collectors: [
|
|
5171
5810
|
offersCollector,
|
|
5172
|
-
|
|
5811
|
+
morphoV2Collector,
|
|
5173
5812
|
positionsCollector,
|
|
5174
5813
|
pricesCollector
|
|
5175
5814
|
]
|
|
@@ -5374,12 +6013,13 @@ var ObligationResponse_exports = /* @__PURE__ */ __exportAll({ from: () => from$
|
|
|
5374
6013
|
* @constructor
|
|
5375
6014
|
* @param obligation - {@link Obligation}
|
|
5376
6015
|
* @param quote - {@link Quote}
|
|
6016
|
+
* @param chainId - The chain id used to compute `id`.
|
|
5377
6017
|
* @returns The created `ObligationResponse`. {@link ObligationResponse}
|
|
5378
6018
|
*/
|
|
5379
|
-
function from$4(obligation, quote) {
|
|
6019
|
+
function from$4(obligation, quote, chainId) {
|
|
5380
6020
|
return {
|
|
5381
6021
|
id: quote.obligationId,
|
|
5382
|
-
chain_id:
|
|
6022
|
+
chain_id: chainId,
|
|
5383
6023
|
loan_token: obligation.loanToken,
|
|
5384
6024
|
collaterals: obligation.collaterals.map((c) => ({
|
|
5385
6025
|
token: c.asset,
|
|
@@ -5446,12 +6086,7 @@ function from$3(input) {
|
|
|
5446
6086
|
receiver_if_maker_is_seller: input.receiverIfMakerIsSeller
|
|
5447
6087
|
},
|
|
5448
6088
|
offer_hash: input.hash,
|
|
5449
|
-
obligation_id:
|
|
5450
|
-
chainId,
|
|
5451
|
-
loanToken: input.loanToken,
|
|
5452
|
-
collaterals: [...input.collaterals],
|
|
5453
|
-
maturity: input.maturity
|
|
5454
|
-
}),
|
|
6089
|
+
obligation_id: input.obligationId,
|
|
5455
6090
|
chain_id: chainId,
|
|
5456
6091
|
consumed: input.consumed.toString(),
|
|
5457
6092
|
takeable: input.takeable.toString(),
|
|
@@ -6078,10 +6713,6 @@ __decorate([(0, openapi_metadata_decorators.ApiProperty)({
|
|
|
6078
6713
|
type: "boolean",
|
|
6079
6714
|
example: validateOfferExample.buy
|
|
6080
6715
|
})], ValidateOfferRequest.prototype, "buy", void 0);
|
|
6081
|
-
__decorate([(0, openapi_metadata_decorators.ApiProperty)({
|
|
6082
|
-
type: "number",
|
|
6083
|
-
example: validateOfferExample.chain_id
|
|
6084
|
-
})], ValidateOfferRequest.prototype, "chain_id", void 0);
|
|
6085
6716
|
__decorate([(0, openapi_metadata_decorators.ApiProperty)({
|
|
6086
6717
|
type: "string",
|
|
6087
6718
|
example: validateOfferExample.loan_token
|
|
@@ -6099,6 +6730,11 @@ __decorate([(0, openapi_metadata_decorators.ApiProperty)({
|
|
|
6099
6730
|
example: validateOfferExample.receiver_if_maker_is_seller
|
|
6100
6731
|
})], ValidateOfferRequest.prototype, "receiver_if_maker_is_seller", void 0);
|
|
6101
6732
|
var ValidateOffersRequest = class {};
|
|
6733
|
+
__decorate([(0, openapi_metadata_decorators.ApiProperty)({
|
|
6734
|
+
type: "number",
|
|
6735
|
+
description: "Chain id used for chain-scoped validation rules.",
|
|
6736
|
+
example: validateOfferExample.chain_id
|
|
6737
|
+
})], ValidateOffersRequest.prototype, "chain_id", void 0);
|
|
6102
6738
|
__decorate([(0, openapi_metadata_decorators.ApiProperty)({
|
|
6103
6739
|
type: () => [ValidateOfferRequest],
|
|
6104
6740
|
description: "Array of offers in snake_case format. Required, non-empty.",
|
|
@@ -6865,6 +7501,12 @@ function isValidBase64urlJson(val) {
|
|
|
6865
7501
|
function isValidOfferHashCursor(val) {
|
|
6866
7502
|
return /^0x[a-f0-9]{64}$/i.test(val);
|
|
6867
7503
|
}
|
|
7504
|
+
function isValidOfferCursor(val) {
|
|
7505
|
+
const [hash, obligationId, ...rest] = val.split(":");
|
|
7506
|
+
if (rest.length !== 0) return false;
|
|
7507
|
+
if (!hash || !obligationId) return false;
|
|
7508
|
+
return isValidOfferHashCursor(hash) && isValidOfferHashCursor(obligationId);
|
|
7509
|
+
}
|
|
6868
7510
|
const csvArray = (schema) => zod.preprocess((value) => {
|
|
6869
7511
|
if (value === void 0) return void 0;
|
|
6870
7512
|
if (Array.isArray(value)) {
|
|
@@ -6928,7 +7570,7 @@ const GetConfigContractsQueryParams = zod.object({
|
|
|
6928
7570
|
});
|
|
6929
7571
|
const GetOffersQueryParams = PaginationQueryParams.omit({ cursor: true }).extend({
|
|
6930
7572
|
cursor: zod.string().optional().meta({
|
|
6931
|
-
description: "Pagination cursor. Use offer hash
|
|
7573
|
+
description: "Pagination cursor. Use offer hash:obligation_id for maker queries, base64url for obligation queries.",
|
|
6932
7574
|
example: "eyJzaWRlIjoic2VsbCIsImN1cnJlbnRQcmljZSI6IjEwMDAwMDAwMDAwMDAwMDAwMDAiLCJibG9ja051bWJlciI6MSwiYXNzZXRzIjoiMTAwMDAwMDAwMDAwMDAwMDAwMCIsImhhc2giOiIweGRmZDY4NTllM2UwODJkMTkzODlhMWFlYzFiZGFkN2U4ZDkyZDk2YjFhYTc5NDBkYTkxYTMxMjVkMzFlM2JlNWIiLCJ0b3RhbFJldHVybmVkIjoxMCwibm93IjoxNjAwMDAwMDAwfQ"
|
|
6933
7575
|
}),
|
|
6934
7576
|
side: zod.enum(["buy", "sell"]).optional().meta({
|
|
@@ -6955,10 +7597,10 @@ const GetOffersQueryParams = PaginationQueryParams.omit({ cursor: true }).extend
|
|
|
6955
7597
|
return;
|
|
6956
7598
|
}
|
|
6957
7599
|
if (hasMaker) {
|
|
6958
|
-
if (val.cursor !== void 0 && !
|
|
7600
|
+
if (val.cursor !== void 0 && !isValidOfferCursor(val.cursor)) ctx.addIssue({
|
|
6959
7601
|
code: "custom",
|
|
6960
7602
|
path: ["cursor"],
|
|
6961
|
-
message: "Cursor must be
|
|
7603
|
+
message: "Cursor must be in the offer hash:obligation_id format when filtering by maker"
|
|
6962
7604
|
});
|
|
6963
7605
|
return;
|
|
6964
7606
|
}
|
|
@@ -7068,7 +7710,13 @@ const GetBookParams = zod.object({
|
|
|
7068
7710
|
example: "buy"
|
|
7069
7711
|
})
|
|
7070
7712
|
});
|
|
7071
|
-
const ValidateOffersBody = zod.object({
|
|
7713
|
+
const ValidateOffersBody = zod.object({
|
|
7714
|
+
chain_id: zod.number().int().positive("chain_id must be a positive integer").meta({
|
|
7715
|
+
description: "Chain id used for chain-scoped validation rules.",
|
|
7716
|
+
example: 1
|
|
7717
|
+
}),
|
|
7718
|
+
offers: zod.array(zod.unknown()).min(1, { message: "'offers' must contain at least 1 offer" })
|
|
7719
|
+
}).strict();
|
|
7072
7720
|
const GetUserPositionsParams = zod.object({
|
|
7073
7721
|
...PaginationQueryParams.shape,
|
|
7074
7722
|
user_address: zod.string().regex(/^0x[a-fA-F0-9]{40}$/, { error: "User address must be a valid 20-byte address" }).transform((val) => val.toLowerCase()).meta({
|
|
@@ -7207,19 +7855,19 @@ async function getConfigContracts(query, chainRegistry) {
|
|
|
7207
7855
|
});
|
|
7208
7856
|
let cursorContract = null;
|
|
7209
7857
|
if (cursor) try {
|
|
7210
|
-
cursorContract = parseCursor$
|
|
7858
|
+
cursorContract = parseCursor$3(cursor);
|
|
7211
7859
|
} catch (err) {
|
|
7212
7860
|
return failure(err);
|
|
7213
7861
|
}
|
|
7214
7862
|
const startIndex = cursorContract ? findStartIndex$1(contracts, cursorContract) : 0;
|
|
7215
7863
|
const page = contracts.slice(startIndex, startIndex + limit);
|
|
7216
|
-
const nextCursor = startIndex + limit < contracts.length && page.length > 0 ? formatCursor$
|
|
7864
|
+
const nextCursor = startIndex + limit < contracts.length && page.length > 0 ? formatCursor$3(page.at(-1)) : null;
|
|
7217
7865
|
return success({
|
|
7218
7866
|
data: page,
|
|
7219
7867
|
cursor: nextCursor
|
|
7220
7868
|
});
|
|
7221
7869
|
}
|
|
7222
|
-
function parseCursor$
|
|
7870
|
+
function parseCursor$3(cursor) {
|
|
7223
7871
|
const [chain, address] = cursor.split(":", 2);
|
|
7224
7872
|
if (!chain || !address) throw new BadRequestError$1("Cursor must be in the format chain_id:0x...");
|
|
7225
7873
|
return {
|
|
@@ -7227,7 +7875,7 @@ function parseCursor$1(cursor) {
|
|
|
7227
7875
|
address: address.toLowerCase()
|
|
7228
7876
|
};
|
|
7229
7877
|
}
|
|
7230
|
-
function formatCursor$
|
|
7878
|
+
function formatCursor$3(contract) {
|
|
7231
7879
|
return `${contract.chain_id}:${contract.address.toLowerCase()}`;
|
|
7232
7880
|
}
|
|
7233
7881
|
function findStartIndex$1(contracts, cursor) {
|
|
@@ -7470,7 +8118,7 @@ async function getConfigRules(query, chains) {
|
|
|
7470
8118
|
const checksum = buildConfigRulesChecksum(filteredRules);
|
|
7471
8119
|
let cursorRule = null;
|
|
7472
8120
|
if (cursor) try {
|
|
7473
|
-
cursorRule = parseCursor(cursor);
|
|
8121
|
+
cursorRule = parseCursor$2(cursor);
|
|
7474
8122
|
} catch (err) {
|
|
7475
8123
|
return failure(err);
|
|
7476
8124
|
}
|
|
@@ -7478,7 +8126,7 @@ async function getConfigRules(query, chains) {
|
|
|
7478
8126
|
if (cursorRule && chainFilter && !chainFilter.has(cursorRule.chain_id)) return failure(new BadRequestError$1("Cursor chain_id must match requested chains"));
|
|
7479
8127
|
const startIndex = cursorRule ? findStartIndex(filteredRules, cursorRule) : 0;
|
|
7480
8128
|
const page = filteredRules.slice(startIndex, startIndex + limit);
|
|
7481
|
-
const nextCursor = startIndex + limit < filteredRules.length && page.length > 0 ? formatCursor(page.at(-1)) : null;
|
|
8129
|
+
const nextCursor = startIndex + limit < filteredRules.length && page.length > 0 ? formatCursor$2(page.at(-1)) : null;
|
|
7482
8130
|
const response = success({
|
|
7483
8131
|
data: page,
|
|
7484
8132
|
cursor: nextCursor
|
|
@@ -7486,14 +8134,14 @@ async function getConfigRules(query, chains) {
|
|
|
7486
8134
|
response.body.meta.checksum = checksum;
|
|
7487
8135
|
return response;
|
|
7488
8136
|
}
|
|
7489
|
-
function formatCursor(rule) {
|
|
8137
|
+
function formatCursor$2(rule) {
|
|
7490
8138
|
if (rule.type === "maturity") return `maturity:${rule.chain_id}:${rule.timestamp}:${rule.name}`;
|
|
7491
8139
|
if (rule.type === "callback") return `callback:${rule.chain_id}:${rule.callback_type}:${rule.address.toLowerCase()}`;
|
|
7492
8140
|
if (rule.type === "oracle") return `oracle:${rule.chain_id}:${rule.address.toLowerCase()}`;
|
|
7493
8141
|
if (rule.type === "collateral_token") return `collateral_token:${rule.chain_id}:${rule.address.toLowerCase()}`;
|
|
7494
8142
|
return `loan_token:${rule.chain_id}:${rule.address.toLowerCase()}`;
|
|
7495
8143
|
}
|
|
7496
|
-
function parseCursor(cursor) {
|
|
8144
|
+
function parseCursor$2(cursor) {
|
|
7497
8145
|
const [type, chain, ...rest] = cursor.split(":");
|
|
7498
8146
|
if (!type || !chain || rest.length === 0) throw new BadRequestError$1("Cursor must be in the format type:chain_id:<value>");
|
|
7499
8147
|
if (!isConfigRuleType(type)) throw new BadRequestError$1("Cursor has an invalid rule type");
|
|
@@ -7786,23 +8434,22 @@ function create$16(parameters) {
|
|
|
7786
8434
|
const loanTokenFilter = loanTokens !== void 0 && loanTokens.length > 0 ? drizzle_orm.sql`(${drizzle_orm.sql.join(loanTokens.map((token) => drizzle_orm.sql`LOWER(${obligations.loanToken}) = ${token.toLowerCase()}`), drizzle_orm.sql` OR `)})` : void 0;
|
|
7787
8435
|
const collateralFilter = collateralTokens !== void 0 && collateralTokens.length > 0 ? drizzle_orm.sql`EXISTS (
|
|
7788
8436
|
SELECT 1 FROM ${obligationCollateralsV2} oc
|
|
7789
|
-
WHERE oc.
|
|
8437
|
+
WHERE oc.obligation_key = ${obligations.obligationKey}
|
|
7790
8438
|
AND (${drizzle_orm.sql.join(collateralTokens.map((token) => drizzle_orm.sql`LOWER(oc.asset) = ${token.toLowerCase()}`), drizzle_orm.sql` OR `)})
|
|
7791
8439
|
)` : void 0;
|
|
7792
|
-
const bestAskTick = db.select({ askTick: offers.tick }).from(offers).innerJoin(groups, (0, drizzle_orm.and)((0, drizzle_orm.eq)(offers.groupChainId, groups.chainId), (0, drizzle_orm.eq)(offers.groupMaker, groups.maker), (0, drizzle_orm.eq)(offers.group, groups.group))).leftJoin(validations, (0, drizzle_orm.eq)(offers.hash, validations.offerHash)).leftJoin(status, (0, drizzle_orm.eq)(validations.statusId, status.id)).where((0, drizzle_orm.and)((0, drizzle_orm.eq)(offers.obligationId,
|
|
7793
|
-
const bestBidTick = db.select({ bidTick: offers.tick }).from(offers).innerJoin(groups, (0, drizzle_orm.and)((0, drizzle_orm.eq)(offers.groupChainId, groups.chainId), (0, drizzle_orm.eq)(offers.groupMaker, groups.maker), (0, drizzle_orm.eq)(offers.group, groups.group))).leftJoin(validations, (0, drizzle_orm.eq)(offers.hash, validations.offerHash)).leftJoin(status, (0, drizzle_orm.eq)(validations.statusId, status.id)).where((0, drizzle_orm.and)((0, drizzle_orm.eq)(offers.obligationId,
|
|
8440
|
+
const bestAskTick = db.select({ askTick: offers.tick }).from(offers).innerJoin(groups, (0, drizzle_orm.and)((0, drizzle_orm.eq)(offers.groupChainId, groups.chainId), (0, drizzle_orm.eq)(offers.groupMaker, groups.maker), (0, drizzle_orm.eq)(offers.group, groups.group))).leftJoin(validations, (0, drizzle_orm.and)((0, drizzle_orm.eq)(offers.hash, validations.offerHash), (0, drizzle_orm.eq)(offers.obligationId, validations.obligationId))).leftJoin(status, (0, drizzle_orm.eq)(validations.statusId, status.id)).where((0, drizzle_orm.and)((0, drizzle_orm.eq)(offers.obligationId, obligationIdKeys.obligationId), (0, drizzle_orm.eq)(offers.buy, false), (0, drizzle_orm.gte)(offers.expiry, now$3), (0, drizzle_orm.gte)(offers.maturity, now$3), (0, drizzle_orm.lte)(offers.start, now$3), drizzle_orm.sql`(${status.code} IS NULL OR ${status.code} = ${Status.VALID})`)).orderBy((0, drizzle_orm.desc)(offers.tick)).limit(1).as("best_ask_tick");
|
|
8441
|
+
const bestBidTick = db.select({ bidTick: offers.tick }).from(offers).innerJoin(groups, (0, drizzle_orm.and)((0, drizzle_orm.eq)(offers.groupChainId, groups.chainId), (0, drizzle_orm.eq)(offers.groupMaker, groups.maker), (0, drizzle_orm.eq)(offers.group, groups.group))).leftJoin(validations, (0, drizzle_orm.and)((0, drizzle_orm.eq)(offers.hash, validations.offerHash), (0, drizzle_orm.eq)(offers.obligationId, validations.obligationId))).leftJoin(status, (0, drizzle_orm.eq)(validations.statusId, status.id)).where((0, drizzle_orm.and)((0, drizzle_orm.eq)(offers.obligationId, obligationIdKeys.obligationId), (0, drizzle_orm.eq)(offers.buy, true), (0, drizzle_orm.gte)(offers.expiry, now$3), (0, drizzle_orm.gte)(offers.maturity, now$3), (0, drizzle_orm.lte)(offers.start, now$3), drizzle_orm.sql`(${status.code} IS NULL OR ${status.code} = ${Status.VALID})`)).orderBy((0, drizzle_orm.asc)(offers.tick)).limit(1).as("best_bid_tick");
|
|
7794
8442
|
const obligationsWithQuotes = db.select({
|
|
7795
|
-
obligationId:
|
|
7796
|
-
chainId:
|
|
8443
|
+
obligationId: obligationIdKeys.obligationId,
|
|
8444
|
+
chainId: obligationIdKeys.chainId,
|
|
7797
8445
|
loanToken: obligations.loanToken,
|
|
7798
|
-
collaterals: drizzle_orm.sql`ARRAY_AGG(jsonb_build_object('asset', ${obligationCollateralsV2.asset}, 'oracle', ${
|
|
8446
|
+
collaterals: drizzle_orm.sql`ARRAY_AGG(jsonb_build_object('asset', ${obligationCollateralsV2.asset}, 'oracle', ${obligationCollateralsV2.oracleAddress}, 'lltv', ${obligationCollateralsV2.lltv}))`.as("collaterals"),
|
|
7799
8447
|
maturity: obligations.maturity,
|
|
7800
8448
|
askTick: drizzle_orm.sql`MAX(${bestAskTick.askTick})`.as("ask_tick"),
|
|
7801
8449
|
bidTick: drizzle_orm.sql`MAX(${bestBidTick.bidTick})`.as("bid_tick"),
|
|
7802
8450
|
ask: drizzle_orm.sql`COALESCE(MAX(${bestAskTick.askTick}) + 1, 0)`.as("ask"),
|
|
7803
8451
|
bid: drizzle_orm.sql`COALESCE(MAX(${bestBidTick.bidTick}) + 1, 0)`.as("bid")
|
|
7804
|
-
}).from(obligations).innerJoin(obligationCollateralsV2, (0, drizzle_orm.eq)(obligations.
|
|
7805
|
-
AND ${obligationCollateralsV2.oracleAddress} = ${oracles$1.address}`).leftJoinLateral(bestAskTick, drizzle_orm.sql`true`).leftJoinLateral(bestBidTick, drizzle_orm.sql`true`).groupBy(obligations.obligationId).where((0, drizzle_orm.and)(ids !== void 0 && ids.length > 0 ? (0, drizzle_orm.inArray)(obligations.obligationId, ids) : void 0, chainIds !== void 0 && chainIds.length > 0 ? (0, drizzle_orm.inArray)(obligations.chainId, chainIds) : void 0, loanTokenFilter, maturities !== void 0 && maturities.length > 0 ? (0, drizzle_orm.inArray)(obligations.maturity, maturities) : (0, drizzle_orm.gte)(obligations.maturity, now$3), collateralFilter)).as("obligations_with_quotes");
|
|
8452
|
+
}).from(obligationIdKeys).innerJoin(obligations, (0, drizzle_orm.eq)(obligationIdKeys.obligationKey, obligations.obligationKey)).innerJoin(obligationCollateralsV2, (0, drizzle_orm.eq)(obligations.obligationKey, obligationCollateralsV2.obligationKey)).leftJoinLateral(bestAskTick, drizzle_orm.sql`true`).leftJoinLateral(bestBidTick, drizzle_orm.sql`true`).groupBy(obligationIdKeys.obligationId, obligationIdKeys.chainId, obligations.loanToken, obligations.maturity).where((0, drizzle_orm.and)(ids !== void 0 && ids.length > 0 ? (0, drizzle_orm.inArray)(obligationIdKeys.obligationId, ids) : void 0, chainIds !== void 0 && chainIds.length > 0 ? (0, drizzle_orm.inArray)(obligationIdKeys.chainId, chainIds) : void 0, loanTokenFilter, maturities !== void 0 && maturities.length > 0 ? (0, drizzle_orm.inArray)(obligations.maturity, maturities) : (0, drizzle_orm.gte)(obligations.maturity, now$3), collateralFilter)).as("obligations_with_quotes");
|
|
7806
8453
|
const sortColumns = {
|
|
7807
8454
|
id: obligationsWithQuotes.obligationId,
|
|
7808
8455
|
ask: obligationsWithQuotes.ask,
|
|
@@ -7822,22 +8469,25 @@ function create$16(parameters) {
|
|
|
7822
8469
|
}).from(obligationsWithQuotes).where(buildCursorFilter(sortColumns, sort, cursorValues)).orderBy(...buildOrderBy(sortColumns, sort)).limit(limit + 1);
|
|
7823
8470
|
const hasMore = rows.length > limit;
|
|
7824
8471
|
const listedRows = (hasMore ? rows.slice(0, limit) : rows).map((row) => {
|
|
7825
|
-
|
|
7826
|
-
|
|
7827
|
-
|
|
7828
|
-
|
|
7829
|
-
|
|
7830
|
-
|
|
7831
|
-
|
|
7832
|
-
|
|
7833
|
-
|
|
7834
|
-
|
|
7835
|
-
|
|
7836
|
-
|
|
7837
|
-
|
|
7838
|
-
|
|
7839
|
-
|
|
7840
|
-
|
|
8472
|
+
const obligation = from$15({
|
|
8473
|
+
loanToken: row.loanToken,
|
|
8474
|
+
collaterals: row.collaterals.sort((left, right) => left.asset.localeCompare(right.asset)).map((collateral) => from$17({
|
|
8475
|
+
asset: collateral.asset,
|
|
8476
|
+
oracle: collateral.oracle,
|
|
8477
|
+
lltv: from$18(BigInt(collateral.lltv))
|
|
8478
|
+
})),
|
|
8479
|
+
maturity: row.maturity
|
|
8480
|
+
});
|
|
8481
|
+
const quote = from$11({
|
|
8482
|
+
obligationId: row.obligationId,
|
|
8483
|
+
ask: { tick: row.askTick },
|
|
8484
|
+
bid: { tick: row.bidTick }
|
|
8485
|
+
});
|
|
8486
|
+
return {
|
|
8487
|
+
obligationId: row.obligationId,
|
|
8488
|
+
chainId: row.chainId,
|
|
8489
|
+
obligation,
|
|
8490
|
+
quote,
|
|
7841
8491
|
cursorValues: {
|
|
7842
8492
|
id: row.obligationId,
|
|
7843
8493
|
ask: toBigInt(row.ask),
|
|
@@ -7855,6 +8505,8 @@ function create$16(parameters) {
|
|
|
7855
8505
|
}) : null;
|
|
7856
8506
|
return {
|
|
7857
8507
|
obligations: listedRows.map((row) => ({
|
|
8508
|
+
obligationId: row.obligationId,
|
|
8509
|
+
chainId: row.chainId,
|
|
7858
8510
|
obligation: row.obligation,
|
|
7859
8511
|
quote: row.quote
|
|
7860
8512
|
})),
|
|
@@ -7992,7 +8644,7 @@ async function getObligation(params, db) {
|
|
|
7992
8644
|
if (listing.obligations.length === 0) return failure(new NotFoundError("Obligation not found"));
|
|
7993
8645
|
const obligation = listing.obligations[0];
|
|
7994
8646
|
return success({
|
|
7995
|
-
data: from$4(obligation.obligation, obligation.quote),
|
|
8647
|
+
data: from$4(obligation.obligation, obligation.quote, obligation.chainId),
|
|
7996
8648
|
cursor: null
|
|
7997
8649
|
});
|
|
7998
8650
|
} catch (err) {
|
|
@@ -8033,7 +8685,7 @@ async function getObligations$1(queryParameters, db) {
|
|
|
8033
8685
|
limit: query.limit
|
|
8034
8686
|
});
|
|
8035
8687
|
return success({
|
|
8036
|
-
data: listing.obligations.map((item) => from$4(item.obligation, item.quote)),
|
|
8688
|
+
data: listing.obligations.map((item) => from$4(item.obligation, item.quote, item.chainId)),
|
|
8037
8689
|
cursor: listing.nextCursor
|
|
8038
8690
|
});
|
|
8039
8691
|
} catch (err) {
|
|
@@ -8071,10 +8723,10 @@ function create$15(config) {
|
|
|
8071
8723
|
return {
|
|
8072
8724
|
create: async (batches) => {
|
|
8073
8725
|
if (batches.length === 0) return [];
|
|
8074
|
-
const offersRows = batches.flatMap(({ blockNumber, offers }) => offers.map((offer) => ({
|
|
8726
|
+
const offersRows = batches.flatMap(({ blockNumber, offers }) => offers.map(({ offer, obligationId, chainId }) => ({
|
|
8075
8727
|
...serialize(offer),
|
|
8076
|
-
obligationId: obligationId(
|
|
8077
|
-
groupChainId:
|
|
8728
|
+
obligationId: obligationId.toLowerCase(),
|
|
8729
|
+
groupChainId: chainId,
|
|
8078
8730
|
groupMaker: offer.maker.toLowerCase(),
|
|
8079
8731
|
callbackAddress: offer.callback.address.toLowerCase(),
|
|
8080
8732
|
callbackData: offer.callback.data,
|
|
@@ -8084,48 +8736,67 @@ function create$15(config) {
|
|
|
8084
8736
|
if (offersRows.length === 0) return [];
|
|
8085
8737
|
try {
|
|
8086
8738
|
return await db.transaction(async (dbTx) => {
|
|
8087
|
-
const
|
|
8088
|
-
|
|
8739
|
+
const keyOf = (input) => `${input.hash.toLowerCase()}:${input.obligationId.toLowerCase()}`;
|
|
8740
|
+
const selectExisting = async (offers$1) => {
|
|
8741
|
+
if (offers$1.length === 0) return /* @__PURE__ */ new Set();
|
|
8742
|
+
const expected = new Set(offers$1.map((offer) => keyOf({
|
|
8743
|
+
hash: offer.hash,
|
|
8744
|
+
obligationId: offer.obligationId
|
|
8745
|
+
})));
|
|
8089
8746
|
const existing = /* @__PURE__ */ new Set();
|
|
8747
|
+
const hashes = [...new Set(offers$1.map((offer) => offer.hash.toLowerCase()))];
|
|
8090
8748
|
for (const batch of batch$1(hashes, DEFAULT_BATCH_SIZE$1)) {
|
|
8091
|
-
const rows = await dbTx.select({
|
|
8092
|
-
|
|
8749
|
+
const rows = await dbTx.select({
|
|
8750
|
+
hash: offers.hash,
|
|
8751
|
+
obligationId: offers.obligationId
|
|
8752
|
+
}).from(offers).where((0, drizzle_orm.inArray)(offers.hash, batch));
|
|
8753
|
+
for (const row of rows) {
|
|
8754
|
+
const key = keyOf({
|
|
8755
|
+
hash: String(row.hash),
|
|
8756
|
+
obligationId: String(row.obligationId)
|
|
8757
|
+
});
|
|
8758
|
+
if (expected.has(key)) existing.add(key);
|
|
8759
|
+
}
|
|
8093
8760
|
}
|
|
8094
8761
|
return existing;
|
|
8095
8762
|
};
|
|
8096
8763
|
const inserted = [];
|
|
8097
8764
|
for (const batch of batch$1(offersRows, DEFAULT_BATCH_SIZE$1)) {
|
|
8098
8765
|
const rows = await dbTx.insert(offers).values(batch).onConflictDoNothing().returning();
|
|
8099
|
-
inserted.push(...rows.map((row) =>
|
|
8766
|
+
inserted.push(...rows.map((row) => ({
|
|
8767
|
+
hash: row.hash,
|
|
8768
|
+
obligationId: row.obligationId
|
|
8769
|
+
})));
|
|
8100
8770
|
}
|
|
8101
8771
|
const existing = await selectExisting(inserted);
|
|
8102
|
-
return inserted.filter((
|
|
8772
|
+
return inserted.filter((offer) => existing.has(keyOf({
|
|
8773
|
+
hash: offer.hash,
|
|
8774
|
+
obligationId: offer.obligationId
|
|
8775
|
+
})));
|
|
8103
8776
|
});
|
|
8104
8777
|
} catch (err) {
|
|
8105
8778
|
const error = err instanceof Error ? err : new Error(String(err));
|
|
8106
|
-
throw new Error("Offers.create failed. Ensure
|
|
8779
|
+
throw new Error("Offers.create failed. Ensure obligation id keys and groups exist before inserting offers.", { cause: error });
|
|
8107
8780
|
}
|
|
8108
8781
|
},
|
|
8109
8782
|
get: async (parameters) => {
|
|
8110
8783
|
const limit = parameters?.limit ?? DEFAULT_LIMIT$3;
|
|
8111
|
-
const
|
|
8784
|
+
const rawCursor = parameters?.cursor;
|
|
8112
8785
|
const maker = parameters?.maker;
|
|
8113
|
-
|
|
8114
|
-
if (!cursor.startsWith("0x") || cursor.length !== 66) throw new Error("Invalid cursor format");
|
|
8115
|
-
}
|
|
8786
|
+
const cursor = rawCursor !== null && rawCursor !== void 0 ? parseCursor$1(rawCursor) : void 0;
|
|
8116
8787
|
const collateralsLateral = db.select({ collaterals: drizzle_orm.sql`COALESCE(
|
|
8117
8788
|
jsonb_agg(
|
|
8118
8789
|
jsonb_build_object(
|
|
8119
8790
|
'asset', ${obligationCollateralsV2.asset},
|
|
8120
|
-
'oracle', ${
|
|
8791
|
+
'oracle', ${obligationCollateralsV2.oracleAddress},
|
|
8121
8792
|
'lltv', ${obligationCollateralsV2.lltv}
|
|
8122
8793
|
)
|
|
8123
8794
|
),
|
|
8124
8795
|
'[]'::jsonb
|
|
8125
|
-
)`.as("collaterals") }).from(obligationCollateralsV2).
|
|
8126
|
-
AND ${obligationCollateralsV2.oracleAddress} = ${oracles$1.address}`).where((0, drizzle_orm.eq)(obligationCollateralsV2.obligationId, offers.obligationId)).as("collaterals_lateral");
|
|
8796
|
+
)`.as("collaterals") }).from(obligationCollateralsV2).where((0, drizzle_orm.eq)(obligationCollateralsV2.obligationKey, obligationIdKeys.obligationKey)).as("collaterals_lateral");
|
|
8127
8797
|
const rows = (await db.select({
|
|
8128
8798
|
hash: offers.hash,
|
|
8799
|
+
obligationId: offers.obligationId,
|
|
8129
8800
|
maker: offers.groupMaker,
|
|
8130
8801
|
assets: offers.assets,
|
|
8131
8802
|
obligationUnits: offers.obligationUnits,
|
|
@@ -8137,17 +8808,18 @@ function create$15(config) {
|
|
|
8137
8808
|
group: offers.group,
|
|
8138
8809
|
session: offers.session,
|
|
8139
8810
|
buy: offers.buy,
|
|
8140
|
-
chainId:
|
|
8811
|
+
chainId: obligationIdKeys.chainId,
|
|
8141
8812
|
loanToken: obligations.loanToken,
|
|
8142
8813
|
callbackAddress: offers.callbackAddress,
|
|
8143
8814
|
callbackData: offers.callbackData,
|
|
8144
8815
|
receiverIfMakerIsSeller: offers.receiverIfMakerIsSeller,
|
|
8145
8816
|
collaterals: collateralsLateral.collaterals,
|
|
8146
8817
|
blockNumber: offers.blockNumber
|
|
8147
|
-
}).from(offers).innerJoin(
|
|
8818
|
+
}).from(offers).innerJoin(obligationIdKeys, (0, drizzle_orm.eq)(offers.obligationId, obligationIdKeys.obligationId)).innerJoin(obligations, (0, drizzle_orm.eq)(obligationIdKeys.obligationKey, obligations.obligationKey)).innerJoinLateral(collateralsLateral, drizzle_orm.sql`true`).where((0, drizzle_orm.and)(cursor !== void 0 ? (0, drizzle_orm.or)((0, drizzle_orm.gt)(offers.hash, cursor.hash), (0, drizzle_orm.and)((0, drizzle_orm.eq)(offers.hash, cursor.hash), (0, drizzle_orm.gt)(offers.obligationId, cursor.obligationId))) : void 0, maker !== void 0 ? (0, drizzle_orm.eq)(offers.groupMaker, maker.toLowerCase()) : void 0)).orderBy((0, drizzle_orm.asc)(offers.hash), (0, drizzle_orm.asc)(offers.obligationId)).limit(limit)).map((row) => {
|
|
8148
8819
|
const receiverIfMakerIsSeller = (row.receiverIfMakerIsSeller ?? row.maker).toLowerCase();
|
|
8149
8820
|
return {
|
|
8150
8821
|
hash: row.hash,
|
|
8822
|
+
obligationId: row.obligationId,
|
|
8151
8823
|
maker: row.maker,
|
|
8152
8824
|
assets: BigInt(row.assets),
|
|
8153
8825
|
obligationUnits: BigInt(row.obligationUnits),
|
|
@@ -8179,7 +8851,10 @@ function create$15(config) {
|
|
|
8179
8851
|
});
|
|
8180
8852
|
return {
|
|
8181
8853
|
rows,
|
|
8182
|
-
nextCursor: rows.length === limit ?
|
|
8854
|
+
nextCursor: rows.length === limit ? formatCursor$1({
|
|
8855
|
+
hash: rows[rows.length - 1].hash,
|
|
8856
|
+
obligationId: rows[rows.length - 1].obligationId
|
|
8857
|
+
}) : null
|
|
8183
8858
|
};
|
|
8184
8859
|
},
|
|
8185
8860
|
delete: async (parameters) => {
|
|
@@ -8202,7 +8877,7 @@ function create$15(config) {
|
|
|
8202
8877
|
const query = ({ side }) => db.selectDistinctOn([offers.obligationId], {
|
|
8203
8878
|
obligationId: offers.obligationId,
|
|
8204
8879
|
tick: offers.tick
|
|
8205
|
-
}).from(offers).innerJoin(groups, (0, drizzle_orm.and)((0, drizzle_orm.eq)(offers.groupChainId, groups.chainId), (0, drizzle_orm.eq)(offers.groupMaker, groups.maker), (0, drizzle_orm.eq)(offers.group, groups.group))).leftJoin(validations, (0, drizzle_orm.eq)(offers.hash, validations.offerHash)).leftJoin(status, (0, drizzle_orm.eq)(validations.statusId, status.id)).where((0, drizzle_orm.and)((0, drizzle_orm.inArray)(offers.obligationId, obligationIds), (0, drizzle_orm.eq)(offers.buy, side === "buy"), (0, drizzle_orm.gte)(offers.expiry, now$2), (0, drizzle_orm.gte)(offers.maturity, now$2), (0, drizzle_orm.lte)(offers.start, now$2), drizzle_orm.sql`(${status.code} IS NULL OR ${status.code} = ${Status.VALID})`)).orderBy(offers.obligationId, side === "buy" ? drizzle_orm.sql`${offers.tick} ASC` : drizzle_orm.sql`${offers.tick} DESC`);
|
|
8880
|
+
}).from(offers).innerJoin(groups, (0, drizzle_orm.and)((0, drizzle_orm.eq)(offers.groupChainId, groups.chainId), (0, drizzle_orm.eq)(offers.groupMaker, groups.maker), (0, drizzle_orm.eq)(offers.group, groups.group))).leftJoin(validations, (0, drizzle_orm.and)((0, drizzle_orm.eq)(offers.hash, validations.offerHash), (0, drizzle_orm.eq)(offers.obligationId, validations.obligationId))).leftJoin(status, (0, drizzle_orm.eq)(validations.statusId, status.id)).where((0, drizzle_orm.and)((0, drizzle_orm.inArray)(offers.obligationId, obligationIds), (0, drizzle_orm.eq)(offers.buy, side === "buy"), (0, drizzle_orm.gte)(offers.expiry, now$2), (0, drizzle_orm.gte)(offers.maturity, now$2), (0, drizzle_orm.lte)(offers.start, now$2), drizzle_orm.sql`(${status.code} IS NULL OR ${status.code} = ${Status.VALID})`)).orderBy(offers.obligationId, side === "buy" ? drizzle_orm.sql`${offers.tick} ASC` : drizzle_orm.sql`${offers.tick} DESC`);
|
|
8206
8881
|
const [bestBuys, bestSells] = await Promise.all([query({ side: "buy" }), query({ side: "sell" })]);
|
|
8207
8882
|
const quotes = /* @__PURE__ */ new Map();
|
|
8208
8883
|
for (const row of bestSells) quotes.set(row.obligationId, {
|
|
@@ -8232,6 +8907,134 @@ function create$15(config) {
|
|
|
8232
8907
|
}
|
|
8233
8908
|
};
|
|
8234
8909
|
}
|
|
8910
|
+
const HEX_32$2 = /^0x[a-fA-F0-9]{64}$/;
|
|
8911
|
+
function parseCursor$1(cursor) {
|
|
8912
|
+
const [hash, obligationId] = cursor.split(":");
|
|
8913
|
+
if (!hash || !obligationId || !HEX_32$2.test(hash) || !HEX_32$2.test(obligationId)) throw new Error("Invalid cursor format");
|
|
8914
|
+
return {
|
|
8915
|
+
hash: hash.toLowerCase(),
|
|
8916
|
+
obligationId: obligationId.toLowerCase()
|
|
8917
|
+
};
|
|
8918
|
+
}
|
|
8919
|
+
function formatCursor$1(input) {
|
|
8920
|
+
return `${input.hash.toLowerCase()}:${input.obligationId.toLowerCase()}`;
|
|
8921
|
+
}
|
|
8922
|
+
|
|
8923
|
+
//#endregion
|
|
8924
|
+
//#region src/database/domains/Trees.ts
|
|
8925
|
+
/**
|
|
8926
|
+
* Creates a Trees domain instance for managing merkle tree metadata.
|
|
8927
|
+
*
|
|
8928
|
+
* @param config - Configuration with database instance
|
|
8929
|
+
* @returns TreesDomain instance
|
|
8930
|
+
*/
|
|
8931
|
+
function create$14(config) {
|
|
8932
|
+
const db = config.db;
|
|
8933
|
+
return {
|
|
8934
|
+
upsert: async (trees$1) => {
|
|
8935
|
+
if (trees$1.length === 0) return [];
|
|
8936
|
+
try {
|
|
8937
|
+
return await db.transaction(async (dbTx) => {
|
|
8938
|
+
const roots = [];
|
|
8939
|
+
for (const { root, signature } of trees$1) {
|
|
8940
|
+
const normalizedRoot = root.toLowerCase();
|
|
8941
|
+
const normalizedSignature = signature.toLowerCase();
|
|
8942
|
+
roots.push(normalizedRoot);
|
|
8943
|
+
await dbTx.insert(trees).values({
|
|
8944
|
+
root: normalizedRoot,
|
|
8945
|
+
rootSignature: normalizedSignature
|
|
8946
|
+
}).onConflictDoUpdate({
|
|
8947
|
+
target: [trees.root],
|
|
8948
|
+
set: {
|
|
8949
|
+
rootSignature: normalizedSignature,
|
|
8950
|
+
createdAt: drizzle_orm.sql`NOW()`
|
|
8951
|
+
}
|
|
8952
|
+
});
|
|
8953
|
+
}
|
|
8954
|
+
return roots;
|
|
8955
|
+
});
|
|
8956
|
+
} catch (err) {
|
|
8957
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
8958
|
+
throw new Error("Trees.upsert failed. Ensure obligations and offers exist before upserting roots.", { cause: error });
|
|
8959
|
+
}
|
|
8960
|
+
},
|
|
8961
|
+
upsertPaths: async (paths) => {
|
|
8962
|
+
if (paths.length === 0) return;
|
|
8963
|
+
const rows = paths.map((path) => ({
|
|
8964
|
+
offerHash: path.offerHash.toLowerCase(),
|
|
8965
|
+
obligationId: path.obligationId.toLowerCase(),
|
|
8966
|
+
treeRoot: path.treeRoot.toLowerCase(),
|
|
8967
|
+
proofNodes: concatenateProofs(path.proof)
|
|
8968
|
+
}));
|
|
8969
|
+
try {
|
|
8970
|
+
for (const batch of batch$1(rows, DEFAULT_BATCH_SIZE$1)) await db.insert(merklePaths).values(batch).onConflictDoUpdate({
|
|
8971
|
+
target: [merklePaths.offerHash, merklePaths.obligationId],
|
|
8972
|
+
set: {
|
|
8973
|
+
treeRoot: drizzle_orm.sql`excluded.tree_root`,
|
|
8974
|
+
proofNodes: drizzle_orm.sql`excluded.proof_nodes`,
|
|
8975
|
+
createdAt: drizzle_orm.sql`NOW()`
|
|
8976
|
+
}
|
|
8977
|
+
});
|
|
8978
|
+
} catch (err) {
|
|
8979
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
8980
|
+
throw new Error("Trees.upsertPaths failed. Ensure offers and roots exist before inserting merkle paths.", { cause: error });
|
|
8981
|
+
}
|
|
8982
|
+
},
|
|
8983
|
+
getAttestations: async (references) => {
|
|
8984
|
+
if (references.length === 0) return /* @__PURE__ */ new Map();
|
|
8985
|
+
const normalizedReferences = references.map((reference) => ({
|
|
8986
|
+
offerHash: reference.offerHash.toLowerCase(),
|
|
8987
|
+
obligationId: reference.obligationId.toLowerCase()
|
|
8988
|
+
}));
|
|
8989
|
+
const hashes = [...new Set(normalizedReferences.map((reference) => reference.offerHash))];
|
|
8990
|
+
const obligationIds = [...new Set(normalizedReferences.map((reference) => reference.obligationId))];
|
|
8991
|
+
const results = await db.select({
|
|
8992
|
+
offerHash: merklePaths.offerHash,
|
|
8993
|
+
obligationId: merklePaths.obligationId,
|
|
8994
|
+
treeRoot: merklePaths.treeRoot,
|
|
8995
|
+
proofNodes: merklePaths.proofNodes,
|
|
8996
|
+
rootSignature: trees.rootSignature
|
|
8997
|
+
}).from(merklePaths).innerJoin(trees, (0, drizzle_orm.eq)(merklePaths.treeRoot, trees.root)).where(drizzle_orm.sql`${(0, drizzle_orm.inArray)(merklePaths.offerHash, hashes)} AND ${(0, drizzle_orm.inArray)(merklePaths.obligationId, obligationIds)}`);
|
|
8998
|
+
const expectedKeys = new Set(normalizedReferences.map(toAttestationKey));
|
|
8999
|
+
const attestationMap = /* @__PURE__ */ new Map();
|
|
9000
|
+
for (const row of results) {
|
|
9001
|
+
const key = toAttestationKey({
|
|
9002
|
+
offerHash: row.offerHash,
|
|
9003
|
+
obligationId: row.obligationId
|
|
9004
|
+
});
|
|
9005
|
+
if (!expectedKeys.has(key)) continue;
|
|
9006
|
+
attestationMap.set(key, {
|
|
9007
|
+
root: row.treeRoot.toLowerCase(),
|
|
9008
|
+
signature: row.rootSignature.toLowerCase(),
|
|
9009
|
+
proof: splitProofs(row.proofNodes)
|
|
9010
|
+
});
|
|
9011
|
+
}
|
|
9012
|
+
return attestationMap;
|
|
9013
|
+
}
|
|
9014
|
+
};
|
|
9015
|
+
}
|
|
9016
|
+
/**
|
|
9017
|
+
* Concatenates an array of 32-byte hex hashes into a single hex string.
|
|
9018
|
+
* Empty arrays return "0x".
|
|
9019
|
+
*/
|
|
9020
|
+
function concatenateProofs(proofs) {
|
|
9021
|
+
if (proofs.length === 0) return "0x";
|
|
9022
|
+
return `0x${proofs.map((proof) => proof.toLowerCase().slice(2)).join("")}`;
|
|
9023
|
+
}
|
|
9024
|
+
/**
|
|
9025
|
+
* Splits a concatenated hex string back into an array of 32-byte hex hashes.
|
|
9026
|
+
* Returns empty array for "0x" or empty string.
|
|
9027
|
+
*/
|
|
9028
|
+
function splitProofs(concatenated) {
|
|
9029
|
+
if (!concatenated || concatenated === "0x" || concatenated.length <= 2) return [];
|
|
9030
|
+
const hex = concatenated.slice(2);
|
|
9031
|
+
const proofs = [];
|
|
9032
|
+
for (let i = 0; i < hex.length; i += 64) proofs.push(`0x${hex.slice(i, i + 64).toLowerCase()}`);
|
|
9033
|
+
return proofs;
|
|
9034
|
+
}
|
|
9035
|
+
function toAttestationKey(offer) {
|
|
9036
|
+
return `${offer.offerHash.toLowerCase()}:${offer.obligationId.toLowerCase()}`;
|
|
9037
|
+
}
|
|
8235
9038
|
|
|
8236
9039
|
//#endregion
|
|
8237
9040
|
//#region src/api/Controllers/getOffers.ts
|
|
@@ -8243,23 +9046,20 @@ function create$15(config) {
|
|
|
8243
9046
|
*/
|
|
8244
9047
|
async function getOffersQuery(db, parameters) {
|
|
8245
9048
|
const limit = parameters?.limit ?? DEFAULT_LIMIT$3;
|
|
8246
|
-
const
|
|
9049
|
+
const rawCursor = parameters?.cursor;
|
|
8247
9050
|
const maker = parameters?.maker;
|
|
8248
|
-
|
|
8249
|
-
if (!cursor.startsWith("0x") || cursor.length !== 66) throw new Error("Invalid cursor format");
|
|
8250
|
-
}
|
|
9051
|
+
const cursor = maker && rawCursor !== void 0 && rawCursor !== null ? parseMakerCursor(rawCursor) : void 0;
|
|
8251
9052
|
const now = Math.floor((Date.now() - 1) / 1e3);
|
|
8252
9053
|
const collateralsLateral = db.select({ collaterals: drizzle_orm.sql`COALESCE(
|
|
8253
9054
|
jsonb_agg(
|
|
8254
9055
|
jsonb_build_object(
|
|
8255
9056
|
'asset', ${obligationCollateralsV2.asset},
|
|
8256
|
-
'oracle', ${
|
|
9057
|
+
'oracle', ${obligationCollateralsV2.oracleAddress},
|
|
8257
9058
|
'lltv', ${obligationCollateralsV2.lltv}
|
|
8258
9059
|
)
|
|
8259
9060
|
),
|
|
8260
9061
|
'[]'::jsonb
|
|
8261
|
-
)`.as("collaterals") }).from(obligationCollateralsV2).
|
|
8262
|
-
AND ${obligationCollateralsV2.oracleAddress} = ${oracles$1.address}`).where((0, drizzle_orm.eq)(obligationCollateralsV2.obligationId, offers.obligationId)).as("collaterals_lateral");
|
|
9062
|
+
)`.as("collaterals") }).from(obligationCollateralsV2).where((0, drizzle_orm.eq)(obligationCollateralsV2.obligationKey, obligationIdKeys.obligationKey)).as("collaterals_lateral");
|
|
8263
9063
|
const lotBalanceExpr = drizzle_orm.sql`GREATEST(0, LEAST(
|
|
8264
9064
|
COALESCE(${positions.balance}, 0)::numeric
|
|
8265
9065
|
+ COALESCE((
|
|
@@ -8304,6 +9104,7 @@ async function getOffersQuery(db, parameters) {
|
|
|
8304
9104
|
AND LOWER(${lots.user}) = LOWER(${callbacks.positionUser})
|
|
8305
9105
|
AND LOWER(${lots.group}) = LOWER(${offers.group})
|
|
8306
9106
|
WHERE ${offersCallbacks.offerHash} = ${offers.hash}
|
|
9107
|
+
AND ${offersCallbacks.obligationId} = ${offers.obligationId}
|
|
8307
9108
|
ORDER BY
|
|
8308
9109
|
${callbacks.positionChainId},
|
|
8309
9110
|
LOWER(${callbacks.positionContract}),
|
|
@@ -8313,6 +9114,7 @@ async function getOffersQuery(db, parameters) {
|
|
|
8313
9114
|
), 0)`;
|
|
8314
9115
|
const rows = (await db.select({
|
|
8315
9116
|
hash: offers.hash,
|
|
9117
|
+
obligationId: offers.obligationId,
|
|
8316
9118
|
maker: offers.groupMaker,
|
|
8317
9119
|
assets: offers.assets,
|
|
8318
9120
|
obligationUnits: offers.obligationUnits,
|
|
@@ -8325,7 +9127,7 @@ async function getOffersQuery(db, parameters) {
|
|
|
8325
9127
|
group: offers.group,
|
|
8326
9128
|
session: offers.session,
|
|
8327
9129
|
buy: offers.buy,
|
|
8328
|
-
chainId:
|
|
9130
|
+
chainId: obligationIdKeys.chainId,
|
|
8329
9131
|
loanToken: obligations.loanToken,
|
|
8330
9132
|
callbackAddress: offers.callbackAddress,
|
|
8331
9133
|
callbackData: offers.callbackData,
|
|
@@ -8342,7 +9144,7 @@ async function getOffersQuery(db, parameters) {
|
|
|
8342
9144
|
)
|
|
8343
9145
|
END
|
|
8344
9146
|
))`.as("takeable")
|
|
8345
|
-
}).from(offers).innerJoin(
|
|
9147
|
+
}).from(offers).innerJoin(obligationIdKeys, (0, drizzle_orm.eq)(offers.obligationId, obligationIdKeys.obligationId)).innerJoin(obligations, (0, drizzle_orm.eq)(obligationIdKeys.obligationKey, obligations.obligationKey)).innerJoin(groups, (0, drizzle_orm.and)((0, drizzle_orm.eq)(offers.groupChainId, groups.chainId), (0, drizzle_orm.eq)(offers.groupMaker, groups.maker), (0, drizzle_orm.eq)(offers.group, groups.group))).innerJoinLateral(collateralsLateral, drizzle_orm.sql`true`).where((0, drizzle_orm.and)(cursor !== void 0 ? cursor.obligationId === void 0 ? (0, drizzle_orm.gt)(offers.hash, cursor.hash) : (0, drizzle_orm.or)((0, drizzle_orm.gt)(offers.hash, cursor.hash), (0, drizzle_orm.and)((0, drizzle_orm.eq)(offers.hash, cursor.hash), (0, drizzle_orm.gt)(offers.obligationId, cursor.obligationId))) : void 0, maker !== void 0 ? (0, drizzle_orm.eq)(offers.groupMaker, maker.toLowerCase()) : void 0, (0, drizzle_orm.gte)(offers.expiry, now), (0, drizzle_orm.gte)(offers.maturity, now), maker === void 0 ? drizzle_orm.sql`GREATEST(0,
|
|
8346
9148
|
CASE WHEN ${offers.buy} = false
|
|
8347
9149
|
THEN ${offers.assets}::numeric - ${groups.consumed}::numeric
|
|
8348
9150
|
ELSE LEAST(
|
|
@@ -8350,10 +9152,11 @@ async function getOffersQuery(db, parameters) {
|
|
|
8350
9152
|
${availableExpr}::numeric
|
|
8351
9153
|
)
|
|
8352
9154
|
END
|
|
8353
|
-
) > 0` : void 0)).orderBy((0, drizzle_orm.asc)(offers.hash)).limit(limit)).map((row) => {
|
|
9155
|
+
) > 0` : void 0)).orderBy((0, drizzle_orm.asc)(offers.hash), (0, drizzle_orm.asc)(offers.obligationId)).limit(limit)).map((row) => {
|
|
8354
9156
|
const receiverIfMakerIsSeller = (row.receiverIfMakerIsSeller ?? row.maker).toLowerCase();
|
|
8355
9157
|
return {
|
|
8356
9158
|
hash: row.hash,
|
|
9159
|
+
obligationId: row.obligationId,
|
|
8357
9160
|
maker: row.maker,
|
|
8358
9161
|
assets: BigInt(row.assets),
|
|
8359
9162
|
obligationUnits: BigInt(row.obligationUnits),
|
|
@@ -8385,7 +9188,7 @@ async function getOffersQuery(db, parameters) {
|
|
|
8385
9188
|
});
|
|
8386
9189
|
return {
|
|
8387
9190
|
rows,
|
|
8388
|
-
nextCursor: rows.length === limit ? rows[rows.length - 1].hash : null
|
|
9191
|
+
nextCursor: rows.length === limit ? maker === void 0 ? rows[rows.length - 1].hash : formatOfferCursor(rows[rows.length - 1]) : null
|
|
8389
9192
|
};
|
|
8390
9193
|
}
|
|
8391
9194
|
async function getOffers$1(queryParameters, db) {
|
|
@@ -8404,12 +9207,18 @@ async function getOffers$1(queryParameters, db) {
|
|
|
8404
9207
|
cursor: query.cursor,
|
|
8405
9208
|
limit: query.limit
|
|
8406
9209
|
});
|
|
8407
|
-
const
|
|
8408
|
-
|
|
9210
|
+
const offers = rows.map((row) => ({
|
|
9211
|
+
offerHash: row.hash,
|
|
9212
|
+
obligationId: row.obligationId
|
|
9213
|
+
}));
|
|
9214
|
+
const attestationMap = await db.trees.getAttestations(offers);
|
|
8409
9215
|
return success({
|
|
8410
9216
|
data: rows.map((row) => {
|
|
8411
|
-
const
|
|
8412
|
-
|
|
9217
|
+
const key = toAttestationKey({
|
|
9218
|
+
offerHash: row.hash,
|
|
9219
|
+
obligationId: row.obligationId
|
|
9220
|
+
});
|
|
9221
|
+
const attestation = attestationMap.get(key);
|
|
8413
9222
|
return from$3({
|
|
8414
9223
|
...row,
|
|
8415
9224
|
...attestation
|
|
@@ -8427,6 +9236,19 @@ async function getOffers$1(queryParameters, db) {
|
|
|
8427
9236
|
return failure(err);
|
|
8428
9237
|
}
|
|
8429
9238
|
}
|
|
9239
|
+
function parseMakerCursor(cursor) {
|
|
9240
|
+
const [rawHash, rawObligationId, ...tail] = cursor.split(":");
|
|
9241
|
+
if (tail.length > 0) throw new Error("Invalid cursor format");
|
|
9242
|
+
if (!rawHash || !rawObligationId || !HEX_32$1.test(rawHash) || !HEX_32$1.test(rawObligationId)) throw new Error("Invalid cursor format");
|
|
9243
|
+
return {
|
|
9244
|
+
hash: rawHash.toLowerCase(),
|
|
9245
|
+
obligationId: rawObligationId.toLowerCase()
|
|
9246
|
+
};
|
|
9247
|
+
}
|
|
9248
|
+
function formatOfferCursor(row) {
|
|
9249
|
+
return `${row.hash.toLowerCase()}:${row.obligationId.toLowerCase()}`;
|
|
9250
|
+
}
|
|
9251
|
+
const HEX_32$1 = /^0x[a-fA-F0-9]{64}$/;
|
|
8430
9252
|
|
|
8431
9253
|
//#endregion
|
|
8432
9254
|
//#region src/api/Controllers/getUserPositions.ts
|
|
@@ -8468,7 +9290,8 @@ async function validateOffers(body, gatekeeper) {
|
|
|
8468
9290
|
const logger = getLogger();
|
|
8469
9291
|
const result = safeParse("validate_offers", body, (issue) => issue.message);
|
|
8470
9292
|
if (!result.success) return failure(new BadRequestError$1(result.error.issues[0]?.message ?? "Invalid request body"));
|
|
8471
|
-
const { offers: rawOffers } = result.data;
|
|
9293
|
+
const { offers: rawOffers, chain_id: rawChainId } = result.data;
|
|
9294
|
+
const chainId = rawChainId;
|
|
8472
9295
|
const parsedOffers = [];
|
|
8473
9296
|
const offerIndexByHash = /* @__PURE__ */ new Map();
|
|
8474
9297
|
for (let i = 0; i < rawOffers.length; i++) {
|
|
@@ -8487,7 +9310,10 @@ async function validateOffers(body, gatekeeper) {
|
|
|
8487
9310
|
}
|
|
8488
9311
|
}
|
|
8489
9312
|
try {
|
|
8490
|
-
const { issues } = await gatekeeper.isAllowed(
|
|
9313
|
+
const { issues } = await gatekeeper.isAllowed({
|
|
9314
|
+
offers: parsedOffers,
|
|
9315
|
+
chainId
|
|
9316
|
+
});
|
|
8491
9317
|
if (issues.length > 0) {
|
|
8492
9318
|
const mappedIssues = issues.map((issue) => {
|
|
8493
9319
|
const index = offerIndexByHash.get(hash(issue.item));
|
|
@@ -8548,14 +9374,14 @@ var Controllers_exports = /* @__PURE__ */ __exportAll({
|
|
|
8548
9374
|
//#region src/api/Api.ts
|
|
8549
9375
|
function from$1(config) {
|
|
8550
9376
|
const { db, gatekeeper, port, chainRegistry } = config;
|
|
8551
|
-
return create$
|
|
9377
|
+
return create$13({
|
|
8552
9378
|
port,
|
|
8553
9379
|
db,
|
|
8554
9380
|
gatekeeper,
|
|
8555
9381
|
chainRegistry
|
|
8556
9382
|
});
|
|
8557
9383
|
}
|
|
8558
|
-
function create$
|
|
9384
|
+
function create$13(params) {
|
|
8559
9385
|
return { serve: () => serve(params) };
|
|
8560
9386
|
}
|
|
8561
9387
|
/**
|
|
@@ -8682,7 +9508,7 @@ var RouterApi_exports = /* @__PURE__ */ __exportAll({
|
|
|
8682
9508
|
RouterStatusResponse: () => RouterStatusResponse,
|
|
8683
9509
|
UsersController: () => UsersController,
|
|
8684
9510
|
ValidateController: () => ValidateController,
|
|
8685
|
-
create: () => create$
|
|
9511
|
+
create: () => create$13,
|
|
8686
9512
|
from: () => from$1,
|
|
8687
9513
|
parse: () => parse,
|
|
8688
9514
|
safeParse: () => safeParse
|
|
@@ -8765,7 +9591,6 @@ async function getOffers(apiClient, parameters) {
|
|
|
8765
9591
|
group: offerData.group,
|
|
8766
9592
|
session: offerData.session,
|
|
8767
9593
|
buy: offerData.buy,
|
|
8768
|
-
chain_id: item.chain_id,
|
|
8769
9594
|
loan_token: offerData.obligation.loan_token,
|
|
8770
9595
|
collaterals: offerData.obligation.collaterals.map((collateral) => ({
|
|
8771
9596
|
asset: collateral.token,
|
|
@@ -8813,7 +9638,6 @@ async function getObligations(apiClient, parameters) {
|
|
|
8813
9638
|
}
|
|
8814
9639
|
const obligations = data?.data.map((item) => {
|
|
8815
9640
|
const obligation = fromSnakeCase$2({
|
|
8816
|
-
chain_id: item.chain_id,
|
|
8817
9641
|
loan_token: item.loan_token,
|
|
8818
9642
|
collaterals: item.collaterals.map((collateral) => ({
|
|
8819
9643
|
asset: collateral.token,
|
|
@@ -8822,16 +9646,17 @@ async function getObligations(apiClient, parameters) {
|
|
|
8822
9646
|
})),
|
|
8823
9647
|
maturity: from$16(item.maturity)
|
|
8824
9648
|
});
|
|
8825
|
-
const { obligationId: _, ...
|
|
8826
|
-
|
|
9649
|
+
const { obligationId: _, ...quote } = from$11({
|
|
9650
|
+
obligationId: item.id,
|
|
9651
|
+
ask: { tick: item.ask.tick },
|
|
9652
|
+
bid: { tick: item.bid.tick }
|
|
9653
|
+
});
|
|
9654
|
+
return {
|
|
9655
|
+
id: item.id,
|
|
9656
|
+
chainId: item.chain_id,
|
|
8827
9657
|
...obligation,
|
|
8828
|
-
...
|
|
8829
|
-
obligationId: item.id,
|
|
8830
|
-
ask: { tick: item.ask.tick },
|
|
8831
|
-
bid: { tick: item.bid.tick }
|
|
8832
|
-
})
|
|
9658
|
+
...quote
|
|
8833
9659
|
};
|
|
8834
|
-
return returned;
|
|
8835
9660
|
}) ?? [];
|
|
8836
9661
|
return {
|
|
8837
9662
|
cursor: data?.cursor ?? null,
|
|
@@ -8878,13 +9703,15 @@ var drizzle_exports = /* @__PURE__ */ __exportAll({
|
|
|
8878
9703
|
VERSION: () => VERSION,
|
|
8879
9704
|
VERSIONED_TABLE_NAMES: () => VERSIONED_TABLE_NAMES,
|
|
8880
9705
|
callbacks: () => callbacks,
|
|
8881
|
-
chains: () => chains
|
|
9706
|
+
chains: () => chains,
|
|
8882
9707
|
collectors: () => collectors,
|
|
8883
9708
|
consumedEvents: () => consumedEvents,
|
|
8884
9709
|
groups: () => groups,
|
|
8885
9710
|
lots: () => lots,
|
|
9711
|
+
lotsPositions: () => lotsPositions,
|
|
8886
9712
|
merklePaths: () => merklePaths,
|
|
8887
9713
|
obligationCollateralsV2: () => obligationCollateralsV2,
|
|
9714
|
+
obligationIdKeys: () => obligationIdKeys,
|
|
8888
9715
|
obligations: () => obligations,
|
|
8889
9716
|
offers: () => offers,
|
|
8890
9717
|
offersCallbacks: () => offersCallbacks,
|
|
@@ -8901,14 +9728,14 @@ var drizzle_exports = /* @__PURE__ */ __exportAll({
|
|
|
8901
9728
|
//#endregion
|
|
8902
9729
|
//#region src/database/domains/Blocks.ts
|
|
8903
9730
|
/** Postgres implementation. */
|
|
8904
|
-
const create$
|
|
9731
|
+
const create$12 = (config) => {
|
|
8905
9732
|
const { db, chainRegistry } = config;
|
|
8906
9733
|
const getChain = async (chainId) => {
|
|
8907
9734
|
const rows = await db.select({
|
|
8908
|
-
chainId: chains
|
|
8909
|
-
blockNumber: chains
|
|
8910
|
-
epoch: chains
|
|
8911
|
-
}).from(chains
|
|
9735
|
+
chainId: chains.chainId,
|
|
9736
|
+
blockNumber: chains.blockNumber,
|
|
9737
|
+
epoch: chains.epoch
|
|
9738
|
+
}).from(chains).where((0, drizzle_orm.eq)(chains.chainId, chainId)).limit(1);
|
|
8912
9739
|
if (rows.length === 0) throw new Error(`Chain state not initialized for chain ${chainId}. Call blocks.init first.`);
|
|
8913
9740
|
const row = rows[0];
|
|
8914
9741
|
return {
|
|
@@ -8936,11 +9763,11 @@ const create$13 = (config) => {
|
|
|
8936
9763
|
};
|
|
8937
9764
|
const getChains = async (parameters) => {
|
|
8938
9765
|
return (await db.select({
|
|
8939
|
-
chainId: chains
|
|
8940
|
-
blockNumber: chains
|
|
8941
|
-
epoch: chains
|
|
8942
|
-
updatedAt: chains
|
|
8943
|
-
}).from(chains
|
|
9766
|
+
chainId: chains.chainId,
|
|
9767
|
+
blockNumber: chains.blockNumber,
|
|
9768
|
+
epoch: chains.epoch,
|
|
9769
|
+
updatedAt: chains.updatedAt
|
|
9770
|
+
}).from(chains).where(parameters?.chainId !== void 0 ? (0, drizzle_orm.eq)(chains.chainId, parameters.chainId) : drizzle_orm.sql`TRUE`).orderBy((0, drizzle_orm.asc)(chains.chainId))).map((row) => ({
|
|
8944
9771
|
chainId: row.chainId,
|
|
8945
9772
|
blockNumber: Number(row.blockNumber),
|
|
8946
9773
|
epoch: BigInt(row.epoch),
|
|
@@ -8966,14 +9793,14 @@ const create$13 = (config) => {
|
|
|
8966
9793
|
const name = parameters.collectorName.toLowerCase();
|
|
8967
9794
|
const deploymentBlock = chainRegistry.getById(parameters.chainId)?.custom?.mempool.blockCreated ?? 0;
|
|
8968
9795
|
const { chain, collector } = await db.transaction(async (dbTx) => {
|
|
8969
|
-
const chainRows = await dbTx.insert(chains
|
|
9796
|
+
const chainRows = await dbTx.insert(chains).values({
|
|
8970
9797
|
chainId: parameters.chainId,
|
|
8971
9798
|
blockNumber: deploymentBlock
|
|
8972
9799
|
}).onConflictDoUpdate({
|
|
8973
|
-
target: chains
|
|
9800
|
+
target: chains.chainId,
|
|
8974
9801
|
set: {
|
|
8975
|
-
blockNumber: drizzle_orm.sql`${chains
|
|
8976
|
-
epoch: drizzle_orm.sql`${chains
|
|
9802
|
+
blockNumber: drizzle_orm.sql`${chains.blockNumber}`,
|
|
9803
|
+
epoch: drizzle_orm.sql`${chains.epoch}`
|
|
8977
9804
|
}
|
|
8978
9805
|
}).returning();
|
|
8979
9806
|
if (chainRows.length === 0) throw new Error(`Failed to initialize chain state for chain ${parameters.chainId}`);
|
|
@@ -9013,28 +9840,28 @@ const create$13 = (config) => {
|
|
|
9013
9840
|
const advanceChain = async (parameters) => {
|
|
9014
9841
|
if (parameters.blockNumber < 0) throw new Error("Block number cannot be negative");
|
|
9015
9842
|
if (parameters.epoch < 0n) throw new Error("Epoch cannot be negative");
|
|
9016
|
-
if ((await db.update(chains
|
|
9843
|
+
if ((await db.update(chains).set({
|
|
9017
9844
|
blockNumber: parameters.blockNumber,
|
|
9018
9845
|
epoch: parameters.epoch.toString(),
|
|
9019
9846
|
updatedAt: drizzle_orm.sql`now()`
|
|
9020
|
-
}).where((0, drizzle_orm.eq)(chains
|
|
9847
|
+
}).where((0, drizzle_orm.eq)(chains.chainId, parameters.chainId)).returning()).length === 0) throw new Error(`Chain state not initialized for chain ${parameters.chainId}. Call blocks.init first.`);
|
|
9021
9848
|
};
|
|
9022
9849
|
const advanceCollector = async (parameters) => {
|
|
9023
9850
|
if (parameters.blockNumber < 0) throw new Error("Block number cannot be negative");
|
|
9024
9851
|
if (parameters.epoch < 0n) throw new Error("Epoch cannot be negative");
|
|
9025
9852
|
const name = parameters.collectorName.toLowerCase();
|
|
9026
9853
|
const chain = db.select({
|
|
9027
|
-
chainId: chains
|
|
9028
|
-
currentEpoch: chains
|
|
9029
|
-
currentBlockNumber: chains
|
|
9030
|
-
}).from(chains
|
|
9854
|
+
chainId: chains.chainId,
|
|
9855
|
+
currentEpoch: chains.epoch,
|
|
9856
|
+
currentBlockNumber: chains.blockNumber
|
|
9857
|
+
}).from(chains).where((0, drizzle_orm.eq)(chains.chainId, parameters.chainId)).as("chain");
|
|
9031
9858
|
const hasReorgHappened = (await db.select().from(collectors).leftJoin(chain, (0, drizzle_orm.eq)(collectors.chainId, chain.chainId)).where((0, drizzle_orm.and)((0, drizzle_orm.eq)(collectors.chainId, parameters.chainId), (0, drizzle_orm.eq)(collectors.name, name), (0, drizzle_orm.gt)(chain.currentEpoch, collectors.epoch), (0, drizzle_orm.eq)(chain.currentEpoch, parameters.epoch.toString()), (0, drizzle_orm.gte)(collectors.blockNumber, parameters.blockNumber))).limit(1)).length > 0;
|
|
9032
9859
|
if ((await db.update(collectors).set({
|
|
9033
9860
|
blockNumber: parameters.blockNumber,
|
|
9034
9861
|
epoch: parameters.epoch.toString(),
|
|
9035
9862
|
updatedAt: drizzle_orm.sql`now()`
|
|
9036
9863
|
}).from(chain).where((0, drizzle_orm.and)((0, drizzle_orm.eq)(collectors.chainId, parameters.chainId), (0, drizzle_orm.eq)(collectors.name, name), (0, drizzle_orm.eq)(chain.currentEpoch, parameters.epoch.toString()), (0, drizzle_orm.gte)(chain.currentBlockNumber, parameters.blockNumber), ...hasReorgHappened ? [] : [(0, drizzle_orm.lte)(collectors.blockNumber, parameters.blockNumber)])).returning()).length > 0) return;
|
|
9037
|
-
if ((await db.select({ chainId: chains
|
|
9864
|
+
if ((await db.select({ chainId: chains.chainId }).from(chains).where((0, drizzle_orm.eq)(chains.chainId, parameters.chainId)).limit(1)).length === 0) throw new Error(`Chain state not initialized for chain ${parameters.chainId}. Call blocks.init first.`);
|
|
9038
9865
|
if ((await db.select({ chainId: collectors.chainId }).from(collectors).where((0, drizzle_orm.and)((0, drizzle_orm.eq)(collectors.chainId, parameters.chainId), (0, drizzle_orm.eq)(collectors.name, name))).limit(1)).length === 0) throw new Error(`Collector state not initialized for ${name} on chain ${parameters.chainId}. Call blocks.init first.`);
|
|
9039
9866
|
throw new Error(`A chain reorg has happened on chain ${parameters.chainId}, update of the collector ${name} is aborted`);
|
|
9040
9867
|
};
|
|
@@ -9082,7 +9909,7 @@ const create$13 = (config) => {
|
|
|
9082
9909
|
//#region src/database/domains/Book.ts
|
|
9083
9910
|
const DEFAULT_LIMIT$2 = 100;
|
|
9084
9911
|
const MAX_TOTAL_OFFERS = 500;
|
|
9085
|
-
function create$
|
|
9912
|
+
function create$11(config) {
|
|
9086
9913
|
const db = config.db;
|
|
9087
9914
|
const logger = getLogger();
|
|
9088
9915
|
const getOffers = async (parameters) => {
|
|
@@ -9168,18 +9995,17 @@ async function _getOffers(db, params) {
|
|
|
9168
9995
|
const { obligationId, side, now, priceSortDirection, cursor, limit } = params;
|
|
9169
9996
|
const raw = await db.execute(drizzle_orm.sql`
|
|
9170
9997
|
WITH collats AS MATERIALIZED (
|
|
9171
|
-
SELECT
|
|
9998
|
+
SELECT oia.obligation_id,
|
|
9172
9999
|
COALESCE(jsonb_agg(jsonb_build_object(
|
|
9173
10000
|
'asset', oc.asset,
|
|
9174
|
-
'oracle',
|
|
10001
|
+
'oracle', oc.oracle_address,
|
|
9175
10002
|
'lltv', oc.lltv
|
|
9176
10003
|
) ORDER BY oc.asset), '[]'::jsonb) AS collaterals
|
|
9177
|
-
FROM ${
|
|
9178
|
-
JOIN ${
|
|
9179
|
-
ON
|
|
9180
|
-
|
|
9181
|
-
|
|
9182
|
-
GROUP BY oc.obligation_id
|
|
10004
|
+
FROM ${obligationIdKeys} oia
|
|
10005
|
+
JOIN ${obligationCollateralsV2} oc
|
|
10006
|
+
ON oc.obligation_key = oia.obligation_key
|
|
10007
|
+
WHERE oia.obligation_id = ${obligationId}
|
|
10008
|
+
GROUP BY oia.obligation_id
|
|
9183
10009
|
),
|
|
9184
10010
|
winners AS (
|
|
9185
10011
|
SELECT DISTINCT ON (o.group_chain_id, o.group_maker, o."group_group")
|
|
@@ -9187,6 +10013,7 @@ async function _getOffers(db, params) {
|
|
|
9187
10013
|
FROM ${offers} o
|
|
9188
10014
|
LEFT JOIN ${validations} v
|
|
9189
10015
|
ON v.offer_hash = o.hash
|
|
10016
|
+
AND v.obligation_id = o.obligation_id
|
|
9190
10017
|
LEFT JOIN ${status} s
|
|
9191
10018
|
ON s.id = v.status_id
|
|
9192
10019
|
WHERE o.obligation_id = ${obligationId}
|
|
@@ -9213,8 +10040,10 @@ async function _getOffers(db, params) {
|
|
|
9213
10040
|
ON g.chain_id = w.group_chain_id
|
|
9214
10041
|
AND g.maker = w.group_maker
|
|
9215
10042
|
AND g."group" = w."group_group"
|
|
10043
|
+
JOIN ${obligationIdKeys} oia
|
|
10044
|
+
ON oia.obligation_id = w.obligation_id
|
|
9216
10045
|
JOIN ${obligations} obl
|
|
9217
|
-
ON obl.
|
|
10046
|
+
ON obl.obligation_key = oia.obligation_key
|
|
9218
10047
|
),
|
|
9219
10048
|
paged AS (
|
|
9220
10049
|
SELECT e.*
|
|
@@ -9313,7 +10142,9 @@ async function _getOffers(db, params) {
|
|
|
9313
10142
|
END
|
|
9314
10143
|
)) AS lot_balance
|
|
9315
10144
|
FROM paged p
|
|
9316
|
-
LEFT JOIN ${offersCallbacks} oc
|
|
10145
|
+
LEFT JOIN ${offersCallbacks} oc
|
|
10146
|
+
ON oc.offer_hash = p.hash
|
|
10147
|
+
AND oc.obligation_id = p.obligation_id
|
|
9317
10148
|
LEFT JOIN ${callbacks} c ON c.id = oc.callback_id
|
|
9318
10149
|
LEFT JOIN ${lots} l
|
|
9319
10150
|
ON l.chain_id = c.position_chain_id
|
|
@@ -9398,11 +10229,13 @@ async function _getOffers(db, params) {
|
|
|
9398
10229
|
AND NOT EXISTS (
|
|
9399
10230
|
SELECT 1 FROM ${offersCallbacks} oc2
|
|
9400
10231
|
WHERE oc2.offer_hash = p.hash
|
|
10232
|
+
AND oc2.obligation_id = p.obligation_id
|
|
9401
10233
|
)
|
|
9402
10234
|
)
|
|
9403
10235
|
-- Final SELECT with inline takeable computation
|
|
9404
10236
|
SELECT
|
|
9405
10237
|
oc.hash,
|
|
10238
|
+
oc.obligation_id,
|
|
9406
10239
|
oc.group_maker,
|
|
9407
10240
|
oc.assets,
|
|
9408
10241
|
oc.obligation_units,
|
|
@@ -9451,6 +10284,7 @@ async function _getOffers(db, params) {
|
|
|
9451
10284
|
const receiverIfMakerIsSeller = (row.receiver_if_maker_is_seller ?? row.group_maker).toLowerCase();
|
|
9452
10285
|
return {
|
|
9453
10286
|
hash: row.hash,
|
|
10287
|
+
obligationId: row.obligation_id,
|
|
9454
10288
|
maker: row.group_maker,
|
|
9455
10289
|
assets: BigInt(row.assets),
|
|
9456
10290
|
obligationUnits: BigInt(row.obligation_units ?? 0),
|
|
@@ -9550,7 +10384,7 @@ let LevelCursor;
|
|
|
9550
10384
|
* @param db - Database core instance.
|
|
9551
10385
|
* @returns Callbacks domain. {@link CallbacksDomain}
|
|
9552
10386
|
*/
|
|
9553
|
-
function create$
|
|
10387
|
+
function create$10(db) {
|
|
9554
10388
|
return {
|
|
9555
10389
|
upsert: async (inputs) => {
|
|
9556
10390
|
if (inputs.length === 0) return;
|
|
@@ -9564,18 +10398,21 @@ function create$11(db) {
|
|
|
9564
10398
|
idCache.set(preimage, id);
|
|
9565
10399
|
return id;
|
|
9566
10400
|
};
|
|
9567
|
-
for (const { offerHash, callbacks } of inputs) {
|
|
10401
|
+
for (const { offerHash, obligationId, callbacks } of inputs) {
|
|
9568
10402
|
const normalizedOfferHash = offerHash.toLowerCase();
|
|
10403
|
+
const normalizedObligationId = obligationId.toLowerCase();
|
|
9569
10404
|
for (const callback of callbacks) {
|
|
9570
10405
|
const normalized = {
|
|
9571
10406
|
chainId: callback.chainId,
|
|
9572
10407
|
contract: callback.contract.toLowerCase(),
|
|
9573
10408
|
user: callback.user.toLowerCase(),
|
|
9574
|
-
amount: callback.amount
|
|
10409
|
+
amount: callback.amount,
|
|
10410
|
+
positionTypeId: callback.positionTypeId
|
|
9575
10411
|
};
|
|
9576
10412
|
const id = callbackId(normalized);
|
|
9577
10413
|
offersCallbacksRows.push({
|
|
9578
10414
|
offerHash: normalizedOfferHash,
|
|
10415
|
+
obligationId: normalizedObligationId,
|
|
9579
10416
|
callbackId: id
|
|
9580
10417
|
});
|
|
9581
10418
|
if (seenCallbackIds.has(id)) continue;
|
|
@@ -9585,6 +10422,7 @@ function create$11(db) {
|
|
|
9585
10422
|
positionChainId: normalized.chainId,
|
|
9586
10423
|
positionContract: normalized.contract,
|
|
9587
10424
|
positionUser: normalized.user,
|
|
10425
|
+
positionTypeId: normalized.positionTypeId,
|
|
9588
10426
|
amount: normalized.amount.toString()
|
|
9589
10427
|
});
|
|
9590
10428
|
}
|
|
@@ -9605,7 +10443,7 @@ function create$11(db) {
|
|
|
9605
10443
|
|
|
9606
10444
|
//#endregion
|
|
9607
10445
|
//#region src/database/domains/Consumed.ts
|
|
9608
|
-
function create$
|
|
10446
|
+
function create$9(db) {
|
|
9609
10447
|
return {
|
|
9610
10448
|
create: async (events) => {
|
|
9611
10449
|
if (events.length === 0) return;
|
|
@@ -9653,7 +10491,7 @@ function create$10(db) {
|
|
|
9653
10491
|
* @param db - Database core instance.
|
|
9654
10492
|
* @returns Groups domain. {@link GroupsDomain}
|
|
9655
10493
|
*/
|
|
9656
|
-
function create$
|
|
10494
|
+
function create$8(db) {
|
|
9657
10495
|
return { create: async (groups$1) => {
|
|
9658
10496
|
if (groups$1.length === 0) return;
|
|
9659
10497
|
const rows = groups$1.map((group) => ({
|
|
@@ -9669,7 +10507,7 @@ function create$9(db) {
|
|
|
9669
10507
|
|
|
9670
10508
|
//#endregion
|
|
9671
10509
|
//#region src/database/domains/Lots.ts
|
|
9672
|
-
function create$
|
|
10510
|
+
function create$7(db) {
|
|
9673
10511
|
return {
|
|
9674
10512
|
get: async (parameters) => {
|
|
9675
10513
|
const { chainId, user, contract, group, obligationId } = parameters ?? {};
|
|
@@ -9697,6 +10535,17 @@ function create$8(db) {
|
|
|
9697
10535
|
const existing = lotsByKey.get(key);
|
|
9698
10536
|
if (!existing || offer.size > existing.size) lotsByKey.set(key, offer);
|
|
9699
10537
|
}
|
|
10538
|
+
const positionsByKey = /* @__PURE__ */ new Map();
|
|
10539
|
+
for (const offer of lotsByKey.values()) {
|
|
10540
|
+
const posKey = `${offer.positionChainId}-${offer.positionContract}-${offer.positionUser}`.toLowerCase();
|
|
10541
|
+
if (!positionsByKey.has(posKey)) positionsByKey.set(posKey, {
|
|
10542
|
+
chainId: offer.positionChainId,
|
|
10543
|
+
contract: offer.positionContract.toLowerCase(),
|
|
10544
|
+
user: offer.positionUser.toLowerCase(),
|
|
10545
|
+
positionTypeId: offer.positionTypeId
|
|
10546
|
+
});
|
|
10547
|
+
}
|
|
10548
|
+
for (const row of positionsByKey.values()) await db.insert(lotsPositions).values(row).onConflictDoNothing();
|
|
9700
10549
|
for (const offer of lotsByKey.values()) if ((await db.select().from(lots).where((0, drizzle_orm.and)((0, drizzle_orm.eq)(lots.chainId, offer.positionChainId), (0, drizzle_orm.eq)(lots.contract, offer.positionContract.toLowerCase()), (0, drizzle_orm.eq)(lots.user, offer.positionUser.toLowerCase()), (0, drizzle_orm.eq)(lots.group, offer.group.toLowerCase()), (0, drizzle_orm.eq)(lots.obligationId, offer.obligationId.toLowerCase()))).limit(1)).length === 0) {
|
|
9701
10550
|
const maxUpperResult = await db.select({ maxUpper: drizzle_orm.sql`COALESCE(MAX(${lots.upper}::numeric), 0)` }).from(lots).where((0, drizzle_orm.and)((0, drizzle_orm.eq)(lots.chainId, offer.positionChainId), (0, drizzle_orm.eq)(lots.contract, offer.positionContract.toLowerCase()), (0, drizzle_orm.eq)(lots.user, offer.positionUser.toLowerCase()), (0, drizzle_orm.eq)(lots.obligationId, offer.obligationId.toLowerCase())));
|
|
9702
10551
|
const newLower = BigInt(maxUpperResult[0]?.maxUpper ?? "0");
|
|
@@ -9722,58 +10571,72 @@ function create$8(db) {
|
|
|
9722
10571
|
* @param db - Database core instance.
|
|
9723
10572
|
* @returns Obligations domain. {@link ObligationsDomain}
|
|
9724
10573
|
*/
|
|
9725
|
-
function create$
|
|
10574
|
+
function create$6(db) {
|
|
9726
10575
|
return {
|
|
9727
10576
|
get: async (parameters) => {
|
|
9728
10577
|
const chainIds = parameters?.chainId;
|
|
9729
10578
|
const now$1 = now();
|
|
9730
10579
|
return (await db.select({
|
|
9731
|
-
|
|
10580
|
+
obligationId: obligationIdKeys.obligationId,
|
|
10581
|
+
chainId: obligationIdKeys.chainId,
|
|
10582
|
+
morphoV2: obligationIdKeys.morphoV2,
|
|
9732
10583
|
loanToken: obligations.loanToken,
|
|
9733
|
-
collaterals: drizzle_orm.sql`ARRAY_AGG(jsonb_build_object('asset', ${obligationCollateralsV2.asset}, 'oracle', ${
|
|
10584
|
+
collaterals: drizzle_orm.sql`ARRAY_AGG(jsonb_build_object('asset', ${obligationCollateralsV2.asset}, 'oracle', ${obligationCollateralsV2.oracleAddress}, 'lltv', ${obligationCollateralsV2.lltv}))`.as("collaterals"),
|
|
9734
10585
|
maturity: obligations.maturity
|
|
9735
|
-
}).from(obligations).innerJoin(obligationCollateralsV2, (0, drizzle_orm.eq)(obligations.
|
|
9736
|
-
|
|
10586
|
+
}).from(obligationIdKeys).innerJoin(obligations, (0, drizzle_orm.eq)(obligationIdKeys.obligationKey, obligations.obligationKey)).innerJoin(obligationCollateralsV2, (0, drizzle_orm.eq)(obligations.obligationKey, obligationCollateralsV2.obligationKey)).groupBy(obligationIdKeys.obligationId, obligationIdKeys.chainId, obligationIdKeys.morphoV2, obligations.loanToken, obligations.maturity).where((0, drizzle_orm.and)(chainIds !== void 0 && chainIds.length > 0 ? (0, drizzle_orm.inArray)(obligationIdKeys.chainId, chainIds) : void 0, (0, drizzle_orm.gte)(obligations.maturity, now$1))).orderBy((0, drizzle_orm.asc)(obligationIdKeys.obligationId))).map((row) => ({
|
|
10587
|
+
obligationId: row.obligationId,
|
|
9737
10588
|
chainId: row.chainId,
|
|
9738
|
-
|
|
9739
|
-
|
|
9740
|
-
|
|
9741
|
-
|
|
9742
|
-
|
|
9743
|
-
|
|
9744
|
-
|
|
10589
|
+
morphoV2: row.morphoV2,
|
|
10590
|
+
obligation: from$15({
|
|
10591
|
+
loanToken: row.loanToken,
|
|
10592
|
+
collaterals: row.collaterals.sort((left, right) => left.asset.localeCompare(right.asset)).map((collateral) => from$17({
|
|
10593
|
+
asset: collateral.asset,
|
|
10594
|
+
oracle: collateral.oracle,
|
|
10595
|
+
lltv: from$18(BigInt(collateral.lltv))
|
|
10596
|
+
})),
|
|
10597
|
+
maturity: row.maturity
|
|
10598
|
+
})
|
|
9745
10599
|
}));
|
|
9746
10600
|
},
|
|
9747
10601
|
create: async (obligations$1) => {
|
|
9748
10602
|
if (obligations$1.length === 0) return;
|
|
9749
|
-
const
|
|
9750
|
-
|
|
9751
|
-
|
|
9752
|
-
|
|
10603
|
+
const obligationsByKey = /* @__PURE__ */ new Map();
|
|
10604
|
+
const obligationIdKeysById = /* @__PURE__ */ new Map();
|
|
10605
|
+
for (const input of obligations$1) {
|
|
10606
|
+
const obligationKey = key(input.obligation).toLowerCase();
|
|
10607
|
+
if (!obligationsByKey.has(obligationKey)) obligationsByKey.set(obligationKey, input.obligation);
|
|
10608
|
+
const obligationId = input.obligationId.toLowerCase();
|
|
10609
|
+
if (!obligationIdKeysById.has(obligationId)) obligationIdKeysById.set(obligationId, input);
|
|
9753
10610
|
}
|
|
9754
10611
|
try {
|
|
9755
10612
|
await db.transaction(async (dbTx) => {
|
|
9756
|
-
const obligationRows =
|
|
9757
|
-
|
|
9758
|
-
|
|
9759
|
-
|
|
9760
|
-
maturity: obligation.maturity
|
|
10613
|
+
const obligationRows = Array.from(obligationsByKey.entries()).map(([obligationKey, item]) => ({
|
|
10614
|
+
obligationKey,
|
|
10615
|
+
loanToken: item.loanToken.toLowerCase(),
|
|
10616
|
+
maturity: item.maturity
|
|
9761
10617
|
}));
|
|
9762
10618
|
for (const batch of batch$1(obligationRows, DEFAULT_BATCH_SIZE$1)) await dbTx.insert(obligations).values(batch).onConflictDoNothing();
|
|
9763
|
-
const
|
|
9764
|
-
|
|
9765
|
-
|
|
10619
|
+
const obligationIdKeyRows = Array.from(obligationIdKeysById.entries()).map(([obligationId, input]) => ({
|
|
10620
|
+
obligationId,
|
|
10621
|
+
obligationKey: key(input.obligation).toLowerCase(),
|
|
10622
|
+
chainId: input.chainId,
|
|
10623
|
+
morphoV2: input.morphoV2.toLowerCase()
|
|
10624
|
+
}));
|
|
10625
|
+
for (const batch of batch$1(obligationIdKeyRows, DEFAULT_BATCH_SIZE$1)) await dbTx.insert(obligationIdKeys).values(batch).onConflictDoNothing();
|
|
10626
|
+
const collateralRows = Array.from(obligationsByKey.entries()).flatMap(([obligationKey, item]) => {
|
|
10627
|
+
return [...item.collaterals].sort((a, b) => a.asset.toLowerCase().localeCompare(b.asset.toLowerCase())).map((collateral, collateralIndex) => ({
|
|
10628
|
+
obligationKey,
|
|
9766
10629
|
asset: collateral.asset.toLowerCase(),
|
|
9767
|
-
oracleChainId: obligation.chainId,
|
|
9768
10630
|
oracleAddress: collateral.oracle.toLowerCase(),
|
|
9769
|
-
lltv: collateral.lltv
|
|
10631
|
+
lltv: collateral.lltv,
|
|
10632
|
+
collateralIndex
|
|
9770
10633
|
}));
|
|
9771
10634
|
});
|
|
9772
10635
|
for (const batch of batch$1(collateralRows, DEFAULT_BATCH_SIZE$1)) await dbTx.insert(obligationCollateralsV2).values(batch).onConflictDoNothing();
|
|
9773
10636
|
});
|
|
9774
10637
|
} catch (err) {
|
|
9775
10638
|
const error = err instanceof Error ? err : new Error(String(err));
|
|
9776
|
-
throw new Error("Obligations.create failed. Ensure
|
|
10639
|
+
throw new Error("Obligations.create failed. Ensure obligation id keys are valid before inserting offers.", { cause: error });
|
|
9777
10640
|
}
|
|
9778
10641
|
}
|
|
9779
10642
|
};
|
|
@@ -9781,7 +10644,7 @@ function create$7(db) {
|
|
|
9781
10644
|
|
|
9782
10645
|
//#endregion
|
|
9783
10646
|
//#region src/database/domains/Offsets.ts
|
|
9784
|
-
function create$
|
|
10647
|
+
function create$5(db) {
|
|
9785
10648
|
return { get: async (parameters) => {
|
|
9786
10649
|
const { chainId, user, contract, group, obligationId } = parameters ?? {};
|
|
9787
10650
|
const conditions = [];
|
|
@@ -9803,7 +10666,7 @@ function create$6(db) {
|
|
|
9803
10666
|
|
|
9804
10667
|
//#endregion
|
|
9805
10668
|
//#region src/database/domains/Oracles.ts
|
|
9806
|
-
function create$
|
|
10669
|
+
function create$4(db) {
|
|
9807
10670
|
return {
|
|
9808
10671
|
get: async ({ chainId }) => {
|
|
9809
10672
|
return (await db.select({
|
|
@@ -9846,19 +10709,20 @@ function create$5(db) {
|
|
|
9846
10709
|
//#endregion
|
|
9847
10710
|
//#region src/database/domains/Positions.ts
|
|
9848
10711
|
const DEFAULT_LIMIT$1 = 100;
|
|
9849
|
-
const create$
|
|
10712
|
+
const create$3 = (db) => {
|
|
9850
10713
|
return {
|
|
9851
10714
|
upsert: async (positions$1) => {
|
|
9852
10715
|
const positionsMap = /* @__PURE__ */ new Map();
|
|
9853
10716
|
for (const p of positions$1) {
|
|
9854
|
-
const key = `${p.chainId}-${p.contract}-${p.user}`.toLowerCase();
|
|
9855
|
-
const zeroKey = `${p.chainId}-${p.contract}-${viem.zeroAddress}`.toLowerCase();
|
|
10717
|
+
const key = `${p.chainId}-${p.contract}-${p.user}-${p.asset}`.toLowerCase();
|
|
10718
|
+
const zeroKey = `${p.chainId}-${p.contract}-${viem.zeroAddress}-${p.asset}`.toLowerCase();
|
|
9856
10719
|
if (!positionsMap.has(zeroKey)) positionsMap.set(zeroKey, {
|
|
9857
10720
|
chainId: p.chainId,
|
|
9858
10721
|
contract: p.contract,
|
|
9859
10722
|
user: viem.zeroAddress,
|
|
9860
10723
|
balance: 0n,
|
|
9861
10724
|
type: p.type,
|
|
10725
|
+
asset: p.asset,
|
|
9862
10726
|
blockNumber: p.blockNumber
|
|
9863
10727
|
});
|
|
9864
10728
|
if (!positionsMap.has(key)) {
|
|
@@ -9869,14 +10733,14 @@ const create$4 = (db) => {
|
|
|
9869
10733
|
}
|
|
9870
10734
|
if (positionsMap.size === 0) return 0;
|
|
9871
10735
|
const rows = Array.from(positionsMap.values()).map((p) => {
|
|
9872
|
-
const positionTypeId =
|
|
10736
|
+
const positionTypeId$1 = positionTypeId(p.type);
|
|
9873
10737
|
return {
|
|
9874
10738
|
chainId: p.chainId,
|
|
9875
10739
|
contract: p.contract.toLowerCase(),
|
|
9876
10740
|
user: p.user.toLowerCase(),
|
|
9877
|
-
positionTypeId,
|
|
10741
|
+
positionTypeId: positionTypeId$1,
|
|
9878
10742
|
...p.balance !== void 0 ? { balance: p.balance.toString() } : {},
|
|
9879
|
-
|
|
10743
|
+
asset: p.asset.toLowerCase(),
|
|
9880
10744
|
blockNumber: p.blockNumber
|
|
9881
10745
|
};
|
|
9882
10746
|
});
|
|
@@ -9886,11 +10750,12 @@ const create$4 = (db) => {
|
|
|
9886
10750
|
target: [
|
|
9887
10751
|
positions.chainId,
|
|
9888
10752
|
positions.contract,
|
|
9889
|
-
positions.user
|
|
10753
|
+
positions.user,
|
|
10754
|
+
positions.positionTypeId,
|
|
10755
|
+
positions.asset
|
|
9890
10756
|
],
|
|
9891
10757
|
set: {
|
|
9892
10758
|
balance: drizzle_orm.sql`EXCLUDED.balance`,
|
|
9893
|
-
asset: drizzle_orm.sql`COALESCE(EXCLUDED.asset, ${positions.asset})`,
|
|
9894
10759
|
blockNumber: drizzle_orm.sql`EXCLUDED.block_number`,
|
|
9895
10760
|
updatedAt: drizzle_orm.sql`NOW()`
|
|
9896
10761
|
},
|
|
@@ -9909,20 +10774,23 @@ const create$4 = (db) => {
|
|
|
9909
10774
|
cursor = {
|
|
9910
10775
|
chainId: parsed.chainId,
|
|
9911
10776
|
contract: parsed.contract,
|
|
9912
|
-
user: parsed.user
|
|
10777
|
+
user: parsed.user,
|
|
10778
|
+
positionTypeId: parsed.positionTypeId ?? 0,
|
|
10779
|
+
asset: parsed.asset ?? ""
|
|
9913
10780
|
};
|
|
9914
10781
|
}
|
|
9915
|
-
const positions$2 = await db.select().from(positions).where((0, drizzle_orm.and)((0, drizzle_orm.ne)(positions.user, viem.zeroAddress), filled === void 0 ? drizzle_orm.sql`true` : drizzle_orm.sql`${positions.balance} IS ${filled === true ? drizzle_orm.sql`NOT` : drizzle_orm.sql``} NULL`, type !== void 0 ? (0, drizzle_orm.eq)(positions.positionTypeId,
|
|
10782
|
+
const positions$2 = await db.select().from(positions).where((0, drizzle_orm.and)((0, drizzle_orm.ne)(positions.user, viem.zeroAddress), filled === void 0 ? drizzle_orm.sql`true` : drizzle_orm.sql`${positions.balance} IS ${filled === true ? drizzle_orm.sql`NOT` : drizzle_orm.sql``} NULL`, type !== void 0 ? (0, drizzle_orm.eq)(positions.positionTypeId, positionTypeId(type)) : drizzle_orm.sql`true`, chainId !== void 0 ? (0, drizzle_orm.eq)(positions.chainId, chainId) : drizzle_orm.sql`true`, (() => {
|
|
9916
10783
|
if (cursor === null || cursor === void 0) return drizzle_orm.sql`true`;
|
|
9917
10784
|
return drizzle_orm.sql`
|
|
9918
|
-
(${chainId === void 0 ? drizzle_orm.sql`"chain_id", ` : drizzle_orm.sql``}"contract", "user") > (${chainId === void 0 ? drizzle_orm.sql`${cursor.chainId}, ` : drizzle_orm.sql``}${cursor.contract}, ${cursor.user})
|
|
10785
|
+
(${chainId === void 0 ? drizzle_orm.sql`"chain_id", ` : drizzle_orm.sql``}"contract", "user", "position_type_id", "asset") > (${chainId === void 0 ? drizzle_orm.sql`${cursor.chainId}, ` : drizzle_orm.sql``}${cursor.contract}, ${cursor.user}, ${cursor.positionTypeId}, ${cursor.asset})
|
|
9919
10786
|
`;
|
|
9920
|
-
})())).orderBy((0, drizzle_orm.asc)(positions.chainId), (0, drizzle_orm.asc)(positions.contract), (0, drizzle_orm.asc)(positions.user), (0, drizzle_orm.asc)(positions.
|
|
10787
|
+
})())).orderBy((0, drizzle_orm.asc)(positions.chainId), (0, drizzle_orm.asc)(positions.contract), (0, drizzle_orm.asc)(positions.user), (0, drizzle_orm.asc)(positions.positionTypeId), (0, drizzle_orm.asc)(positions.asset)).limit(limit);
|
|
9921
10788
|
const nextCursor = positions$2.length === limit ? Buffer.from(JSON.stringify({
|
|
9922
10789
|
chainId: positions$2[positions$2.length - 1].chainId.toString(),
|
|
9923
10790
|
contract: positions$2[positions$2.length - 1].contract,
|
|
9924
10791
|
user: positions$2[positions$2.length - 1].user,
|
|
9925
|
-
|
|
10792
|
+
positionTypeId: positions$2[positions$2.length - 1].positionTypeId,
|
|
10793
|
+
asset: positions$2[positions$2.length - 1].asset
|
|
9926
10794
|
})).toString("base64url") : null;
|
|
9927
10795
|
return {
|
|
9928
10796
|
positions: positions$2.map((p) => ({
|
|
@@ -9931,14 +10799,14 @@ const create$4 = (db) => {
|
|
|
9931
10799
|
user: p.user,
|
|
9932
10800
|
type: Object.values(Type)[p.positionTypeId - 1],
|
|
9933
10801
|
balance: p.balance !== null ? BigInt(p.balance) : void 0,
|
|
9934
|
-
|
|
10802
|
+
asset: p.asset,
|
|
9935
10803
|
blockNumber: p.blockNumber
|
|
9936
10804
|
})),
|
|
9937
10805
|
nextCursor
|
|
9938
10806
|
};
|
|
9939
10807
|
},
|
|
9940
10808
|
getByUser: async (parameters) => {
|
|
9941
|
-
const { user, limit = DEFAULT_LIMIT$1, cursor: encodedCursor } = parameters;
|
|
10809
|
+
const { user, type, limit = DEFAULT_LIMIT$1, cursor: encodedCursor } = parameters;
|
|
9942
10810
|
let cursor = null;
|
|
9943
10811
|
if (encodedCursor !== null && encodedCursor !== void 0) {
|
|
9944
10812
|
const parsed = JSON.parse(Buffer.from(encodedCursor, "base64url").toString("utf8"));
|
|
@@ -9946,6 +10814,8 @@ const create$4 = (db) => {
|
|
|
9946
10814
|
cursor = {
|
|
9947
10815
|
chainId: parsed.chainId,
|
|
9948
10816
|
contract: parsed.contract,
|
|
10817
|
+
positionTypeId: parsed.positionTypeId ?? 0,
|
|
10818
|
+
asset: parsed.asset ?? "",
|
|
9949
10819
|
obligationId: parsed.obligationId ?? null
|
|
9950
10820
|
};
|
|
9951
10821
|
}
|
|
@@ -10033,6 +10903,8 @@ const create$4 = (db) => {
|
|
|
10033
10903
|
p.contract,
|
|
10034
10904
|
p."user",
|
|
10035
10905
|
p.block_number,
|
|
10906
|
+
p.position_type_id,
|
|
10907
|
+
p.asset,
|
|
10036
10908
|
po.obligation_id,
|
|
10037
10909
|
COALESCE(po.reserved_balance, '0') AS reserved_balance
|
|
10038
10910
|
FROM ${positions} p
|
|
@@ -10042,14 +10914,18 @@ const create$4 = (db) => {
|
|
|
10042
10914
|
AND LOWER(po."user") = LOWER(p."user")
|
|
10043
10915
|
WHERE LOWER(p."user") = LOWER(${user})
|
|
10044
10916
|
AND p."user" != ${viem.zeroAddress}
|
|
10045
|
-
${
|
|
10046
|
-
|
|
10917
|
+
${type !== void 0 ? drizzle_orm.sql`AND p.position_type_id = ${positionTypeId(type)}` : drizzle_orm.sql``}
|
|
10918
|
+
${cursor !== null ? drizzle_orm.sql`AND (p.chain_id, p.contract, p.position_type_id, p.asset, COALESCE(po.obligation_id, '')) > (${cursor.chainId}, ${cursor.contract}, ${cursor.positionTypeId}, ${cursor.asset}, ${cursor.obligationId ?? ""})` : drizzle_orm.sql``}
|
|
10919
|
+
ORDER BY p.chain_id ASC, p.contract ASC, p.position_type_id ASC, p.asset ASC, po.obligation_id ASC NULLS FIRST
|
|
10047
10920
|
LIMIT ${limit}
|
|
10048
10921
|
`);
|
|
10049
|
-
const
|
|
10050
|
-
|
|
10051
|
-
|
|
10052
|
-
|
|
10922
|
+
const lastRow = raw.rows[raw.rows.length - 1];
|
|
10923
|
+
const nextCursor = raw.rows.length === limit && lastRow !== void 0 ? Buffer.from(JSON.stringify({
|
|
10924
|
+
chainId: lastRow.chain_id.toString(),
|
|
10925
|
+
contract: lastRow.contract,
|
|
10926
|
+
positionTypeId: lastRow.position_type_id,
|
|
10927
|
+
asset: lastRow.asset,
|
|
10928
|
+
obligationId: lastRow.obligation_id
|
|
10053
10929
|
})).toString("base64url") : null;
|
|
10054
10930
|
return {
|
|
10055
10931
|
positions: raw.rows.map((row) => ({
|
|
@@ -10064,21 +10940,23 @@ const create$4 = (db) => {
|
|
|
10064
10940
|
};
|
|
10065
10941
|
},
|
|
10066
10942
|
setEmptyAfter: async (parameters) => {
|
|
10067
|
-
const { chainId, blockNumber } = parameters;
|
|
10943
|
+
const { chainId, blockNumber, type } = parameters;
|
|
10944
|
+
const typeId = positionTypeId(type);
|
|
10068
10945
|
return await db.transaction(async (tx) => {
|
|
10069
10946
|
const updatedPositions = await tx.update(positions).set({
|
|
10070
10947
|
balance: null,
|
|
10071
10948
|
blockNumber,
|
|
10072
10949
|
updatedAt: drizzle_orm.sql`NOW()`
|
|
10073
|
-
}).where((0, drizzle_orm.and)((0, drizzle_orm.eq)(positions.chainId, chainId), drizzle_orm.sql`${positions.blockNumber} >= ${blockNumber}
|
|
10950
|
+
}).where((0, drizzle_orm.and)((0, drizzle_orm.eq)(positions.chainId, chainId), drizzle_orm.sql`${positions.blockNumber} >= ${blockNumber}`, (0, drizzle_orm.eq)(positions.positionTypeId, typeId))).returning();
|
|
10074
10951
|
if (updatedPositions.length === 0) return 0;
|
|
10075
10952
|
await tx.execute(drizzle_orm.sql`
|
|
10076
10953
|
DELETE FROM ${transfers} t
|
|
10077
|
-
USING (VALUES ${drizzle_orm.sql.join(updatedPositions.map((u) => drizzle_orm.sql`(${u.chainId}::bigint, ${u.contract}::varchar(
|
|
10954
|
+
USING (VALUES ${drizzle_orm.sql.join(updatedPositions.map((u) => drizzle_orm.sql`(${u.chainId}::bigint, ${u.contract}::varchar(66), ${u.user}::varchar(42))`), drizzle_orm.sql`,`)}) AS s(chain_id, "contract", "user")
|
|
10078
10955
|
WHERE
|
|
10079
10956
|
t.chain_id = s.chain_id
|
|
10080
10957
|
AND t."contract" = s."contract"
|
|
10081
10958
|
AND (t."from" = s."user" OR t."to" = s."user")
|
|
10959
|
+
AND t.position_type_id = ${typeId}
|
|
10082
10960
|
`);
|
|
10083
10961
|
return updatedPositions.length;
|
|
10084
10962
|
});
|
|
@@ -10088,33 +10966,35 @@ const create$4 = (db) => {
|
|
|
10088
10966
|
|
|
10089
10967
|
//#endregion
|
|
10090
10968
|
//#region src/database/domains/Transfers.ts
|
|
10091
|
-
const create$
|
|
10092
|
-
|
|
10093
|
-
|
|
10094
|
-
|
|
10095
|
-
|
|
10096
|
-
|
|
10097
|
-
|
|
10098
|
-
|
|
10969
|
+
const create$2 = (db) => ({
|
|
10970
|
+
create: async (transfers$1) => {
|
|
10971
|
+
if (transfers$1.length === 0) return 0;
|
|
10972
|
+
const typeId = positionTypeId(transfers$1[0].type);
|
|
10973
|
+
return await db.transaction(async (dbTx) => {
|
|
10974
|
+
let totalInserted = 0;
|
|
10975
|
+
for (const transfersBatch of batch$1(transfers$1, DEFAULT_BATCH_SIZE$1)) {
|
|
10976
|
+
const { rows: inserted } = await dbTx.execute(drizzle_orm.sql`
|
|
10977
|
+
INSERT INTO ${transfers} (event_id, chain_id, "contract", "from", "to", "value", position_type_id, asset, block_number)
|
|
10978
|
+
SELECT * FROM (VALUES ${drizzle_orm.sql.join(transfersBatch.map((transfer) => drizzle_orm.sql`(${transfer.id}::varchar(128), ${transfer.chainId}::bigint, ${transfer.contract.toLowerCase()}::varchar(66), ${transfer.from.toLowerCase()}::varchar(42), ${transfer.to.toLowerCase()}::varchar(42), ${transfer.value.toString()}::numeric(78, 0), ${typeId}::integer, ${transfer.asset.toLowerCase()}::varchar(42), ${transfer.blockNumber}::bigint)`), drizzle_orm.sql`,`)}) AS v(event_id, chain_id, "contract", "from", "to", "value", position_type_id, asset, block_number)
|
|
10099
10979
|
WHERE
|
|
10100
10980
|
EXISTS (
|
|
10101
10981
|
SELECT 1 FROM ${positions} p
|
|
10102
|
-
WHERE p.chain_id = v.chain_id AND p."contract" = v."contract" AND p."user" = v."from" AND p.balance IS NOT NULL
|
|
10982
|
+
WHERE p.chain_id = v.chain_id AND p."contract" = v."contract" AND p."user" = v."from" AND p.position_type_id = v.position_type_id AND p.asset = v.asset AND p.balance IS NOT NULL
|
|
10103
10983
|
)
|
|
10104
10984
|
AND
|
|
10105
10985
|
EXISTS (
|
|
10106
10986
|
SELECT 1 FROM ${positions} p
|
|
10107
|
-
WHERE p.chain_id = v.chain_id AND p."contract" = v."contract" AND p."user" = v."to" AND p.balance IS NOT NULL
|
|
10987
|
+
WHERE p.chain_id = v.chain_id AND p."contract" = v."contract" AND p."user" = v."to" AND p.position_type_id = v.position_type_id AND p.asset = v.asset AND p.balance IS NOT NULL
|
|
10108
10988
|
)
|
|
10109
10989
|
ON CONFLICT DO NOTHING
|
|
10110
10990
|
RETURNING *;
|
|
10111
10991
|
`);
|
|
10112
|
-
|
|
10113
|
-
|
|
10992
|
+
if (inserted.length === 0) continue;
|
|
10993
|
+
await dbTx.execute(drizzle_orm.sql`
|
|
10114
10994
|
WITH inserted AS (
|
|
10115
10995
|
VALUES ${drizzle_orm.sql.join(inserted.map((t) => {
|
|
10116
|
-
|
|
10117
|
-
|
|
10996
|
+
return drizzle_orm.sql`(${t.chain_id}::bigint, ${t.contract}::varchar(66), ${t.from}::varchar(42), ${t.to}::varchar(42), ${t.value}::numeric(78, 0), ${t.asset}::varchar(42), ${t.block_number}::bigint)`;
|
|
10997
|
+
}), drizzle_orm.sql`,`)}
|
|
10118
10998
|
),
|
|
10119
10999
|
new_transfers AS (
|
|
10120
11000
|
SELECT
|
|
@@ -10123,7 +11003,8 @@ const create$3 = (db) => ({ create: async (transfers$1) => {
|
|
|
10123
11003
|
column3 AS "from",
|
|
10124
11004
|
column4 AS "to",
|
|
10125
11005
|
column5 AS "value",
|
|
10126
|
-
column6 AS
|
|
11006
|
+
column6 AS asset,
|
|
11007
|
+
column7 AS block_number
|
|
10127
11008
|
FROM inserted
|
|
10128
11009
|
),
|
|
10129
11010
|
diffs AS (
|
|
@@ -10132,6 +11013,7 @@ const create$3 = (db) => ({ create: async (transfers$1) => {
|
|
|
10132
11013
|
nt."contract",
|
|
10133
11014
|
nt."from" AS "user",
|
|
10134
11015
|
-nt."value" AS delta,
|
|
11016
|
+
nt.asset,
|
|
10135
11017
|
nt.block_number
|
|
10136
11018
|
FROM new_transfers nt
|
|
10137
11019
|
UNION ALL
|
|
@@ -10140,6 +11022,7 @@ const create$3 = (db) => ({ create: async (transfers$1) => {
|
|
|
10140
11022
|
nt."contract",
|
|
10141
11023
|
nt."to" AS "user",
|
|
10142
11024
|
nt."value" AS delta,
|
|
11025
|
+
nt.asset,
|
|
10143
11026
|
nt.block_number
|
|
10144
11027
|
FROM new_transfers nt
|
|
10145
11028
|
),
|
|
@@ -10149,12 +11032,15 @@ const create$3 = (db) => ({ create: async (transfers$1) => {
|
|
|
10149
11032
|
d."contract",
|
|
10150
11033
|
d."user",
|
|
10151
11034
|
d.delta,
|
|
11035
|
+
d.asset,
|
|
10152
11036
|
d.block_number
|
|
10153
11037
|
FROM diffs d
|
|
10154
11038
|
JOIN ${positions} p
|
|
10155
11039
|
ON p.chain_id = d.chain_id
|
|
10156
11040
|
AND p."contract" = d."contract"
|
|
10157
11041
|
AND p."user" = d."user"
|
|
11042
|
+
AND p.position_type_id = ${typeId}
|
|
11043
|
+
AND p.asset = d.asset
|
|
10158
11044
|
-- Only keep per-event diffs that are at or after the current position block
|
|
10159
11045
|
WHERE d.block_number >= p.block_number
|
|
10160
11046
|
),
|
|
@@ -10163,10 +11049,11 @@ const create$3 = (db) => ({ create: async (transfers$1) => {
|
|
|
10163
11049
|
chain_id,
|
|
10164
11050
|
"contract",
|
|
10165
11051
|
"user",
|
|
11052
|
+
asset,
|
|
10166
11053
|
SUM(delta) AS sum_delta,
|
|
10167
11054
|
MAX(block_number) AS max_block
|
|
10168
11055
|
FROM valid_diffs
|
|
10169
|
-
GROUP BY 1,2,3
|
|
11056
|
+
GROUP BY 1,2,3,4
|
|
10170
11057
|
)
|
|
10171
11058
|
UPDATE ${positions} AS p
|
|
10172
11059
|
SET
|
|
@@ -10178,101 +11065,109 @@ const create$3 = (db) => ({ create: async (transfers$1) => {
|
|
|
10178
11065
|
p.chain_id = a.chain_id
|
|
10179
11066
|
AND p."contract" = a."contract"
|
|
10180
11067
|
AND p."user" = a."user"
|
|
11068
|
+
AND p.asset = a.asset
|
|
11069
|
+
AND p.position_type_id = ${typeId}
|
|
10181
11070
|
`);
|
|
10182
|
-
|
|
10183
|
-
}
|
|
10184
|
-
return totalInserted;
|
|
10185
|
-
});
|
|
10186
|
-
} });
|
|
10187
|
-
|
|
10188
|
-
//#endregion
|
|
10189
|
-
//#region src/database/domains/Trees.ts
|
|
10190
|
-
/**
|
|
10191
|
-
* Creates a Trees domain instance for managing merkle tree metadata.
|
|
10192
|
-
*
|
|
10193
|
-
* @param config - Configuration with database instance
|
|
10194
|
-
* @returns TreesDomain instance
|
|
10195
|
-
*/
|
|
10196
|
-
function create$2(config) {
|
|
10197
|
-
const db = config.db;
|
|
10198
|
-
return {
|
|
10199
|
-
create: async (trees$1) => {
|
|
10200
|
-
if (trees$1.length === 0) return [];
|
|
10201
|
-
try {
|
|
10202
|
-
return await db.transaction(async (dbTx) => {
|
|
10203
|
-
const roots = [];
|
|
10204
|
-
for (const { tree, signature } of trees$1) {
|
|
10205
|
-
const root = tree.root.toLowerCase();
|
|
10206
|
-
roots.push(root);
|
|
10207
|
-
await dbTx.insert(trees).values({
|
|
10208
|
-
root,
|
|
10209
|
-
rootSignature: signature.toLowerCase()
|
|
10210
|
-
}).onConflictDoUpdate({
|
|
10211
|
-
target: [trees.root],
|
|
10212
|
-
set: {
|
|
10213
|
-
rootSignature: signature.toLowerCase(),
|
|
10214
|
-
createdAt: drizzle_orm.sql`NOW()`
|
|
10215
|
-
}
|
|
10216
|
-
});
|
|
10217
|
-
const pathRows = proofs(tree).map((proof) => ({
|
|
10218
|
-
offerHash: hash(proof.offer).toLowerCase(),
|
|
10219
|
-
treeRoot: root,
|
|
10220
|
-
proofNodes: concatenateProofs(proof.path)
|
|
10221
|
-
}));
|
|
10222
|
-
for (const batch of batch$1(pathRows, DEFAULT_BATCH_SIZE$1)) await dbTx.insert(merklePaths).values(batch).onConflictDoUpdate({
|
|
10223
|
-
target: [merklePaths.offerHash],
|
|
10224
|
-
set: {
|
|
10225
|
-
treeRoot: drizzle_orm.sql`excluded.tree_root`,
|
|
10226
|
-
proofNodes: drizzle_orm.sql`excluded.proof_nodes`,
|
|
10227
|
-
createdAt: drizzle_orm.sql`NOW()`
|
|
10228
|
-
}
|
|
10229
|
-
});
|
|
10230
|
-
}
|
|
10231
|
-
return roots;
|
|
10232
|
-
});
|
|
10233
|
-
} catch (err) {
|
|
10234
|
-
const error = err instanceof Error ? err : new Error(String(err));
|
|
10235
|
-
throw new Error("Trees.create failed. Ensure offers exist before inserting merkle paths.", { cause: error });
|
|
11071
|
+
totalInserted += inserted.length;
|
|
10236
11072
|
}
|
|
10237
|
-
|
|
10238
|
-
|
|
10239
|
-
|
|
10240
|
-
|
|
10241
|
-
|
|
10242
|
-
|
|
10243
|
-
|
|
10244
|
-
|
|
10245
|
-
|
|
10246
|
-
|
|
10247
|
-
|
|
10248
|
-
|
|
10249
|
-
|
|
10250
|
-
|
|
10251
|
-
|
|
10252
|
-
|
|
10253
|
-
|
|
10254
|
-
|
|
10255
|
-
|
|
10256
|
-
|
|
10257
|
-
|
|
10258
|
-
|
|
10259
|
-
|
|
10260
|
-
|
|
10261
|
-
|
|
10262
|
-
|
|
10263
|
-
|
|
10264
|
-
|
|
10265
|
-
|
|
10266
|
-
|
|
10267
|
-
|
|
10268
|
-
|
|
10269
|
-
|
|
10270
|
-
|
|
10271
|
-
|
|
10272
|
-
|
|
10273
|
-
|
|
10274
|
-
|
|
10275
|
-
|
|
11073
|
+
return totalInserted;
|
|
11074
|
+
});
|
|
11075
|
+
},
|
|
11076
|
+
delete: async (parameters) => {
|
|
11077
|
+
const { chainId, blockNumberGte, positionTypeId } = parameters;
|
|
11078
|
+
return await db.transaction(async (dbTx) => {
|
|
11079
|
+
const { rows: toDelete } = await dbTx.execute(drizzle_orm.sql`
|
|
11080
|
+
SELECT event_id, chain_id, "contract", "from", "to", "value"::text, asset, block_number
|
|
11081
|
+
FROM ${transfers}
|
|
11082
|
+
WHERE chain_id = ${chainId}
|
|
11083
|
+
AND position_type_id = ${positionTypeId}
|
|
11084
|
+
AND block_number >= ${blockNumberGte}
|
|
11085
|
+
`);
|
|
11086
|
+
if (toDelete.length === 0) return 0;
|
|
11087
|
+
await dbTx.execute(drizzle_orm.sql`
|
|
11088
|
+
WITH to_delete AS (
|
|
11089
|
+
VALUES ${drizzle_orm.sql.join(toDelete.map((t) => drizzle_orm.sql`(${t.chain_id}::bigint, ${t.contract}::varchar(66), ${t.from}::varchar(42), ${t.to}::varchar(42), ${t.value}::numeric(78, 0), ${t.asset}::varchar(42))`), drizzle_orm.sql`,`)}
|
|
11090
|
+
),
|
|
11091
|
+
reverse_diffs AS (
|
|
11092
|
+
SELECT column1 AS chain_id, column2 AS "contract", column3 AS "user", column5 AS delta, column6 AS asset
|
|
11093
|
+
FROM to_delete
|
|
11094
|
+
UNION ALL
|
|
11095
|
+
SELECT column1 AS chain_id, column2 AS "contract", column4 AS "user", -column5 AS delta, column6 AS asset
|
|
11096
|
+
FROM to_delete
|
|
11097
|
+
),
|
|
11098
|
+
aggregated AS (
|
|
11099
|
+
SELECT chain_id, "contract", "user", asset, SUM(delta) AS sum_delta
|
|
11100
|
+
FROM reverse_diffs
|
|
11101
|
+
GROUP BY 1,2,3,4
|
|
11102
|
+
),
|
|
11103
|
+
remaining_max AS (
|
|
11104
|
+
SELECT t.chain_id, t."contract",
|
|
11105
|
+
CASE WHEN t."from" = a."user" THEN t."from" ELSE t."to" END AS "user",
|
|
11106
|
+
t.asset,
|
|
11107
|
+
MAX(t.block_number) AS max_block
|
|
11108
|
+
FROM ${transfers} t
|
|
11109
|
+
JOIN aggregated a
|
|
11110
|
+
ON t.chain_id = a.chain_id AND t."contract" = a."contract"
|
|
11111
|
+
AND t.asset = a.asset
|
|
11112
|
+
AND (t."from" = a."user" OR t."to" = a."user")
|
|
11113
|
+
WHERE t.position_type_id = ${positionTypeId}
|
|
11114
|
+
AND t.block_number < ${blockNumberGte}
|
|
11115
|
+
GROUP BY t.chain_id, t."contract",
|
|
11116
|
+
CASE WHEN t."from" = a."user" THEN t."from" ELSE t."to" END,
|
|
11117
|
+
t.asset
|
|
11118
|
+
)
|
|
11119
|
+
UPDATE ${positions} AS p
|
|
11120
|
+
SET
|
|
11121
|
+
balance = COALESCE(p.balance, 0) + a.sum_delta,
|
|
11122
|
+
block_number = COALESCE(rm.max_block, p.block_number),
|
|
11123
|
+
updated_at = NOW()
|
|
11124
|
+
FROM aggregated a
|
|
11125
|
+
LEFT JOIN remaining_max rm
|
|
11126
|
+
ON rm.chain_id = a.chain_id AND rm."contract" = a."contract" AND rm."user" = a."user" AND rm.asset = a.asset
|
|
11127
|
+
WHERE p.chain_id = a.chain_id
|
|
11128
|
+
AND p."contract" = a."contract"
|
|
11129
|
+
AND p."user" = a."user"
|
|
11130
|
+
AND p.asset = a.asset
|
|
11131
|
+
AND p.position_type_id = ${positionTypeId}
|
|
11132
|
+
`);
|
|
11133
|
+
await dbTx.execute(drizzle_orm.sql`
|
|
11134
|
+
DELETE FROM ${transfers}
|
|
11135
|
+
WHERE chain_id = ${chainId}
|
|
11136
|
+
AND position_type_id = ${positionTypeId}
|
|
11137
|
+
AND block_number >= ${blockNumberGte}
|
|
11138
|
+
`);
|
|
11139
|
+
await dbTx.execute(drizzle_orm.sql`
|
|
11140
|
+
DELETE FROM ${positions} p
|
|
11141
|
+
USING (
|
|
11142
|
+
SELECT DISTINCT chain_id, "contract", "user", asset
|
|
11143
|
+
FROM (
|
|
11144
|
+
SELECT chain_id, "contract", "from" AS "user", asset FROM (
|
|
11145
|
+
VALUES ${drizzle_orm.sql.join(toDelete.map((t) => drizzle_orm.sql`(${t.chain_id}::bigint, ${t.contract}::varchar(66), ${t.from}::varchar(42), ${t.asset}::varchar(42))`), drizzle_orm.sql`,`)}
|
|
11146
|
+
) AS d(chain_id, "contract", "from", asset)
|
|
11147
|
+
UNION
|
|
11148
|
+
SELECT chain_id, "contract", "to" AS "user", asset FROM (
|
|
11149
|
+
VALUES ${drizzle_orm.sql.join(toDelete.map((t) => drizzle_orm.sql`(${t.chain_id}::bigint, ${t.contract}::varchar(66), ${t.to}::varchar(42), ${t.asset}::varchar(42))`), drizzle_orm.sql`,`)}
|
|
11150
|
+
) AS d(chain_id, "contract", "to", asset)
|
|
11151
|
+
) AS combined
|
|
11152
|
+
) AS affected
|
|
11153
|
+
WHERE p.chain_id = affected.chain_id
|
|
11154
|
+
AND p."contract" = affected."contract"
|
|
11155
|
+
AND p."user" = affected."user"
|
|
11156
|
+
AND p.asset = affected.asset
|
|
11157
|
+
AND p.position_type_id = ${positionTypeId}
|
|
11158
|
+
AND NOT EXISTS (
|
|
11159
|
+
SELECT 1 FROM ${transfers} t
|
|
11160
|
+
WHERE t.chain_id = p.chain_id
|
|
11161
|
+
AND t."contract" = p."contract"
|
|
11162
|
+
AND t.asset = p.asset
|
|
11163
|
+
AND t.position_type_id = ${positionTypeId}
|
|
11164
|
+
AND (t."from" = p."user" OR t."to" = p."user")
|
|
11165
|
+
)
|
|
11166
|
+
`);
|
|
11167
|
+
return toDelete.length;
|
|
11168
|
+
});
|
|
11169
|
+
}
|
|
11170
|
+
});
|
|
10276
11171
|
|
|
10277
11172
|
//#endregion
|
|
10278
11173
|
//#region src/database/domains/Validations.ts
|
|
@@ -10281,26 +11176,26 @@ function create$1(db) {
|
|
|
10281
11176
|
return {
|
|
10282
11177
|
get: async (params) => {
|
|
10283
11178
|
const { status: status$1, cursor, limit = DEFAULT_LIMIT } = params ?? {};
|
|
10284
|
-
|
|
10285
|
-
if (!cursor.startsWith("0x") || cursor.length !== 66) throw new Error("Invalid cursor format");
|
|
10286
|
-
}
|
|
11179
|
+
const parsedCursor = cursor !== null && cursor !== void 0 ? parseCursor(cursor) : void 0;
|
|
10287
11180
|
let query = db.select({
|
|
10288
11181
|
offerHash: validations.offerHash,
|
|
11182
|
+
obligationId: validations.obligationId,
|
|
10289
11183
|
code: status.code
|
|
10290
11184
|
}).from(validations).innerJoin(status, (0, drizzle_orm.eq)(validations.statusId, status.id));
|
|
10291
11185
|
if (status$1 !== void 0) query = query.where((0, drizzle_orm.eq)(status.code, status$1));
|
|
10292
|
-
if (
|
|
10293
|
-
const cursorCondition = (0, drizzle_orm.gt)(validations.offerHash,
|
|
11186
|
+
if (parsedCursor !== void 0) {
|
|
11187
|
+
const cursorCondition = (0, drizzle_orm.or)((0, drizzle_orm.gt)(validations.offerHash, parsedCursor.offerHash), (0, drizzle_orm.and)((0, drizzle_orm.eq)(validations.offerHash, parsedCursor.offerHash), (0, drizzle_orm.gt)(validations.obligationId, parsedCursor.obligationId)));
|
|
10294
11188
|
if (status$1 !== void 0) query = query.where((0, drizzle_orm.and)((0, drizzle_orm.eq)(status.code, status$1), cursorCondition));
|
|
10295
11189
|
else query = query.where(cursorCondition);
|
|
10296
11190
|
}
|
|
10297
|
-
const mapped = (await query.orderBy((0, drizzle_orm.asc)(validations.offerHash)).limit(limit)).map((row) => ({
|
|
11191
|
+
const mapped = (await query.orderBy((0, drizzle_orm.asc)(validations.offerHash), (0, drizzle_orm.asc)(validations.obligationId)).limit(limit)).map((row) => ({
|
|
10298
11192
|
offerHash: row.offerHash,
|
|
11193
|
+
obligationId: row.obligationId,
|
|
10299
11194
|
status: row.code
|
|
10300
11195
|
}));
|
|
10301
11196
|
return {
|
|
10302
11197
|
validations: mapped,
|
|
10303
|
-
nextCursor: mapped.length === limit ? mapped[mapped.length - 1]
|
|
11198
|
+
nextCursor: mapped.length === limit ? formatCursor(mapped[mapped.length - 1]) : null
|
|
10304
11199
|
};
|
|
10305
11200
|
},
|
|
10306
11201
|
upsert: async (results) => {
|
|
@@ -10310,6 +11205,7 @@ function create$1(db) {
|
|
|
10310
11205
|
if (invalidStatuses.length > 0) throw new Error(`Unknown validation status: ${invalidStatuses.join(", ")}`);
|
|
10311
11206
|
const normalized = results.map((r) => ({
|
|
10312
11207
|
offerHash: r.offerHash.toLowerCase(),
|
|
11208
|
+
obligationId: r.obligationId.toLowerCase(),
|
|
10313
11209
|
status: r.status
|
|
10314
11210
|
}));
|
|
10315
11211
|
const uniqueStatuses = Array.from(new Set(normalized.map((r) => r.status)));
|
|
@@ -10321,10 +11217,11 @@ function create$1(db) {
|
|
|
10321
11217
|
for (const status of uniqueStatuses) if (!statusMap.has(status)) throw new Error(`Unknown validation status: ${status}`);
|
|
10322
11218
|
const values = normalized.map((row) => ({
|
|
10323
11219
|
offerHash: row.offerHash,
|
|
11220
|
+
obligationId: row.obligationId,
|
|
10324
11221
|
statusId: statusMap.get(row.status)
|
|
10325
11222
|
}));
|
|
10326
11223
|
for (const batch of batch$1(values, DEFAULT_BATCH_SIZE$1)) await db.insert(validations).values(batch).onConflictDoUpdate({
|
|
10327
|
-
target: [validations.offerHash],
|
|
11224
|
+
target: [validations.offerHash, validations.obligationId],
|
|
10328
11225
|
set: {
|
|
10329
11226
|
statusId: drizzle_orm.sql`excluded.status_id`,
|
|
10330
11227
|
updatedAt: drizzle_orm.sql`NOW()`
|
|
@@ -10333,6 +11230,18 @@ function create$1(db) {
|
|
|
10333
11230
|
}
|
|
10334
11231
|
};
|
|
10335
11232
|
}
|
|
11233
|
+
const HEX_32 = /^0x[a-fA-F0-9]{64}$/;
|
|
11234
|
+
function parseCursor(cursor) {
|
|
11235
|
+
const [offerHash, obligationId] = cursor.split(":");
|
|
11236
|
+
if (!offerHash || !obligationId || !HEX_32.test(offerHash) || !HEX_32.test(obligationId)) throw new Error("Invalid cursor format");
|
|
11237
|
+
return {
|
|
11238
|
+
offerHash: offerHash.toLowerCase(),
|
|
11239
|
+
obligationId: obligationId.toLowerCase()
|
|
11240
|
+
};
|
|
11241
|
+
}
|
|
11242
|
+
function formatCursor(input) {
|
|
11243
|
+
return `${input.offerHash.toLowerCase()}:${input.obligationId.toLowerCase()}`;
|
|
11244
|
+
}
|
|
10336
11245
|
|
|
10337
11246
|
//#endregion
|
|
10338
11247
|
//#region src/database/Database.ts
|
|
@@ -10342,23 +11251,23 @@ var Database_exports = /* @__PURE__ */ __exportAll({
|
|
|
10342
11251
|
});
|
|
10343
11252
|
function createDomains(core, chainRegistry) {
|
|
10344
11253
|
return {
|
|
10345
|
-
book: create$
|
|
10346
|
-
blocks: create$
|
|
11254
|
+
book: create$11({ db: core }),
|
|
11255
|
+
blocks: create$12({
|
|
10347
11256
|
db: core,
|
|
10348
11257
|
chainRegistry
|
|
10349
11258
|
}),
|
|
10350
|
-
callbacks: create$
|
|
11259
|
+
callbacks: create$10(core),
|
|
10351
11260
|
offers: create$15({ db: core }),
|
|
10352
|
-
consumed: create$
|
|
10353
|
-
groups: create$
|
|
10354
|
-
lots: create$
|
|
10355
|
-
obligations: create$
|
|
10356
|
-
offsets: create$
|
|
10357
|
-
oracles: create$
|
|
10358
|
-
trees: create$
|
|
11261
|
+
consumed: create$9(core),
|
|
11262
|
+
groups: create$8(core),
|
|
11263
|
+
lots: create$7(core),
|
|
11264
|
+
obligations: create$6(core),
|
|
11265
|
+
offsets: create$5(core),
|
|
11266
|
+
oracles: create$4(core),
|
|
11267
|
+
trees: create$14({ db: core }),
|
|
10359
11268
|
validations: create$1(core),
|
|
10360
|
-
positions: create$
|
|
10361
|
-
transfers: create$
|
|
11269
|
+
positions: create$3(core),
|
|
11270
|
+
transfers: create$2(core)
|
|
10362
11271
|
};
|
|
10363
11272
|
}
|
|
10364
11273
|
function createReaders(core) {
|
|
@@ -10523,7 +11432,7 @@ async function postMigrate(driver) {
|
|
|
10523
11432
|
const tracer = getTracer("db.postMigrate");
|
|
10524
11433
|
await startActiveSpan(tracer, "db.postMigrate", async () => {
|
|
10525
11434
|
await driver.execute(`INSERT INTO "${VERSION}"."status" ("code") VALUES ('${Status.VALID}'), ('${Status.SIMULATION_ERROR}') ON CONFLICT DO NOTHING;`);
|
|
10526
|
-
await driver.execute(`INSERT INTO "${VERSION}"."position_types" ("type") VALUES ('${Type.ERC20}'), ('${Type.VAULT_V1}') ON CONFLICT DO NOTHING;`);
|
|
11435
|
+
await driver.execute(`INSERT INTO "${VERSION}"."position_types" ("type") VALUES ('${Type.ERC20}'), ('${Type.VAULT_V1}'), ('${Type.DEBT_OF}'), ('${Type.COLLATERAL_OF}') ON CONFLICT DO NOTHING;`);
|
|
10527
11436
|
await driver.execute(`
|
|
10528
11437
|
CREATE OR REPLACE FUNCTION apply_group_consumed_stmt_ins()
|
|
10529
11438
|
RETURNS trigger
|
|
@@ -10677,19 +11586,23 @@ async function postMigrate(driver) {
|
|
|
10677
11586
|
BEGIN
|
|
10678
11587
|
DELETE FROM "${VERSION}"."positions" p
|
|
10679
11588
|
USING (
|
|
10680
|
-
SELECT DISTINCT c.position_chain_id, c.position_contract, c.position_user
|
|
11589
|
+
SELECT DISTINCT c.position_chain_id, c.position_contract, c.position_user, c.position_type_id
|
|
10681
11590
|
FROM deleted_rows d
|
|
10682
11591
|
JOIN "${VERSION}"."callbacks" c ON c.id = d.callback_id
|
|
10683
11592
|
) AS affected
|
|
11593
|
+
JOIN "${VERSION}"."position_types" pt ON pt.id = affected.position_type_id
|
|
10684
11594
|
WHERE p.chain_id = affected.position_chain_id
|
|
10685
11595
|
AND p.contract = affected.position_contract
|
|
10686
11596
|
AND p."user" = affected.position_user
|
|
11597
|
+
AND p.position_type_id = affected.position_type_id
|
|
11598
|
+
AND pt.type = 'erc20'
|
|
10687
11599
|
AND NOT EXISTS (
|
|
10688
11600
|
SELECT 1 FROM "${VERSION}"."callbacks" c2
|
|
10689
11601
|
JOIN "${VERSION}"."offers_callbacks" oc ON oc.callback_id = c2.id
|
|
10690
11602
|
WHERE c2.position_chain_id = p.chain_id
|
|
10691
11603
|
AND c2.position_contract = p.contract
|
|
10692
11604
|
AND c2.position_user = p."user"
|
|
11605
|
+
AND c2.position_type_id = p.position_type_id
|
|
10693
11606
|
);
|
|
10694
11607
|
RETURN NULL;
|
|
10695
11608
|
END;
|
|
@@ -10736,7 +11649,7 @@ async function postMigrate(driver) {
|
|
|
10736
11649
|
RETURNS TRIGGER AS $$
|
|
10737
11650
|
DECLARE
|
|
10738
11651
|
orphan_obligation_ids TEXT[];
|
|
10739
|
-
|
|
11652
|
+
orphan_obligation_keys TEXT[];
|
|
10740
11653
|
BEGIN
|
|
10741
11654
|
-- 1. Find orphan obligation IDs
|
|
10742
11655
|
SELECT ARRAY_AGG(DISTINCT obligation_id) INTO orphan_obligation_ids
|
|
@@ -10744,33 +11657,39 @@ async function postMigrate(driver) {
|
|
|
10744
11657
|
WHERE NOT EXISTS (
|
|
10745
11658
|
SELECT 1 FROM "${VERSION}"."offers" ov
|
|
10746
11659
|
WHERE ov.obligation_id = d.obligation_id
|
|
11660
|
+
)
|
|
11661
|
+
AND NOT EXISTS (
|
|
11662
|
+
SELECT 1 FROM "${VERSION}"."positions" p
|
|
11663
|
+
JOIN "${VERSION}"."position_types" pt ON pt.id = p.position_type_id
|
|
11664
|
+
WHERE p."contract" = d.obligation_id
|
|
11665
|
+
AND pt.type IN ('debtOf', 'collateralOf')
|
|
10747
11666
|
);
|
|
10748
11667
|
|
|
10749
|
-
-- 2. If no orphan
|
|
11668
|
+
-- 2. If no orphan obligation IDs, exit early
|
|
10750
11669
|
IF orphan_obligation_ids IS NULL OR array_length(orphan_obligation_ids, 1) IS NULL THEN
|
|
10751
11670
|
RETURN NULL;
|
|
10752
11671
|
END IF;
|
|
10753
11672
|
|
|
10754
|
-
-- 3.
|
|
10755
|
-
|
|
10756
|
-
|
|
10757
|
-
FROM "${VERSION}"."obligation_collaterals_v2" oc
|
|
10758
|
-
WHERE oc.obligation_id = ANY(orphan_obligation_ids);
|
|
11673
|
+
-- 3. Delete orphan obligation id keys
|
|
11674
|
+
DELETE FROM "${VERSION}"."obligation_id_keys" oia
|
|
11675
|
+
WHERE oia.obligation_id = ANY(orphan_obligation_ids);
|
|
10759
11676
|
|
|
10760
|
-
-- 4.
|
|
10761
|
-
|
|
10762
|
-
|
|
11677
|
+
-- 4. Find canonical obligation keys with no remaining obligation id keys
|
|
11678
|
+
SELECT ARRAY_AGG(ob.obligation_key) INTO orphan_obligation_keys
|
|
11679
|
+
FROM "${VERSION}"."obligations" ob
|
|
11680
|
+
WHERE NOT EXISTS (
|
|
11681
|
+
SELECT 1 FROM "${VERSION}"."obligation_id_keys" oia
|
|
11682
|
+
WHERE oia.obligation_key = ob.obligation_key
|
|
11683
|
+
);
|
|
10763
11684
|
|
|
10764
|
-
-- 5.
|
|
10765
|
-
|
|
10766
|
-
|
|
10767
|
-
|
|
10768
|
-
|
|
10769
|
-
|
|
10770
|
-
|
|
10771
|
-
|
|
10772
|
-
AND oc.oracle_address = o.address
|
|
10773
|
-
);
|
|
11685
|
+
-- 5. If no orphan canonical obligations, exit early
|
|
11686
|
+
IF orphan_obligation_keys IS NULL OR array_length(orphan_obligation_keys, 1) IS NULL THEN
|
|
11687
|
+
RETURN NULL;
|
|
11688
|
+
END IF;
|
|
11689
|
+
|
|
11690
|
+
-- 6. Delete orphan canonical obligations (cascades to collaterals)
|
|
11691
|
+
DELETE FROM "${VERSION}"."obligations" ob
|
|
11692
|
+
WHERE ob.obligation_key = ANY(orphan_obligation_keys);
|
|
10774
11693
|
|
|
10775
11694
|
RETURN NULL;
|
|
10776
11695
|
END;
|
|
@@ -10788,16 +11707,21 @@ async function postMigrate(driver) {
|
|
|
10788
11707
|
RETURNS trigger
|
|
10789
11708
|
LANGUAGE plpgsql AS $$
|
|
10790
11709
|
BEGIN
|
|
10791
|
-
|
|
10792
|
-
|
|
10793
|
-
|
|
10794
|
-
|
|
10795
|
-
|
|
10796
|
-
|
|
10797
|
-
|
|
10798
|
-
|
|
10799
|
-
|
|
10800
|
-
|
|
11710
|
+
BEGIN
|
|
11711
|
+
INSERT INTO "${VERSION}"."offsets" (chain_id, "user", contract, "group", obligation_id, value)
|
|
11712
|
+
VALUES (
|
|
11713
|
+
OLD.chain_id,
|
|
11714
|
+
OLD."user",
|
|
11715
|
+
OLD.contract,
|
|
11716
|
+
OLD."group",
|
|
11717
|
+
OLD.obligation_id,
|
|
11718
|
+
OLD.upper::numeric - OLD.lower::numeric
|
|
11719
|
+
)
|
|
11720
|
+
ON CONFLICT (chain_id, "user", contract, "group", obligation_id) DO NOTHING;
|
|
11721
|
+
EXCEPTION WHEN foreign_key_violation THEN
|
|
11722
|
+
-- lots_positions may be gone during cascaded deletes
|
|
11723
|
+
NULL;
|
|
11724
|
+
END;
|
|
10801
11725
|
RETURN OLD;
|
|
10802
11726
|
END;
|
|
10803
11727
|
$$;
|
|
@@ -10820,11 +11744,26 @@ async function postMigrate(driver) {
|
|
|
10820
11744
|
AND l.contract = OLD.contract
|
|
10821
11745
|
AND l."user" = OLD."user"
|
|
10822
11746
|
) THEN
|
|
10823
|
-
-- No lots remain, delete
|
|
11747
|
+
-- No lots remain, delete erc20 positions and their lots_positions bridge rows.
|
|
11748
|
+
-- debtOf/collateralOf positions live independently of offers and must not be deleted here.
|
|
11749
|
+
-- First delete the position (for ERC20, asset = contract).
|
|
10824
11750
|
DELETE FROM "${VERSION}"."positions" p
|
|
10825
|
-
|
|
10826
|
-
|
|
10827
|
-
|
|
11751
|
+
USING "${VERSION}"."lots_positions" lp
|
|
11752
|
+
JOIN "${VERSION}"."position_types" pt ON pt.id = lp.position_type_id
|
|
11753
|
+
WHERE lp.chain_id = OLD.chain_id
|
|
11754
|
+
AND lp.contract = OLD.contract
|
|
11755
|
+
AND lp."user" = OLD."user"
|
|
11756
|
+
AND p.chain_id = lp.chain_id
|
|
11757
|
+
AND p.contract = lp.contract
|
|
11758
|
+
AND p."user" = lp."user"
|
|
11759
|
+
AND p.position_type_id = lp.position_type_id
|
|
11760
|
+
AND pt.type = 'erc20';
|
|
11761
|
+
|
|
11762
|
+
-- Delete the lots_positions bridge row (cascades to offsets via offsets_lots_positions_fk).
|
|
11763
|
+
DELETE FROM "${VERSION}"."lots_positions" lp
|
|
11764
|
+
WHERE lp.chain_id = OLD.chain_id
|
|
11765
|
+
AND lp.contract = OLD.contract
|
|
11766
|
+
AND lp."user" = OLD."user";
|
|
10828
11767
|
END IF;
|
|
10829
11768
|
RETURN NULL;
|
|
10830
11769
|
END;
|
|
@@ -10893,8 +11832,12 @@ function createHttpClient(config) {
|
|
|
10893
11832
|
body: json
|
|
10894
11833
|
};
|
|
10895
11834
|
};
|
|
10896
|
-
const isAllowed = async (
|
|
10897
|
-
const {
|
|
11835
|
+
const isAllowed = async (parameters) => {
|
|
11836
|
+
const { offers, chainId } = parameters;
|
|
11837
|
+
const { statusCode, body } = await validate({
|
|
11838
|
+
chain_id: chainId,
|
|
11839
|
+
offers: offers.map((offer) => toSnakeCase(offer))
|
|
11840
|
+
});
|
|
10898
11841
|
if (statusCode !== 200) {
|
|
10899
11842
|
const errorMessage = extractErrorMessage(body);
|
|
10900
11843
|
throw new Error(`Gatekeeper validation failed: ${errorMessage ?? `status ${statusCode}`}`);
|
|
@@ -11036,11 +11979,12 @@ var Gatekeeper_exports = /* @__PURE__ */ __exportAll({ create: () => create });
|
|
|
11036
11979
|
* @returns Gatekeeper instance. {@link Gatekeeper}
|
|
11037
11980
|
*/
|
|
11038
11981
|
function create(parameters) {
|
|
11039
|
-
const { rules } = parameters;
|
|
11040
|
-
return { isAllowed: async (
|
|
11982
|
+
const { rules: rulesFactory } = parameters;
|
|
11983
|
+
return { isAllowed: async (parameters) => {
|
|
11984
|
+
const { offers, chainId } = parameters;
|
|
11041
11985
|
return await run({
|
|
11042
11986
|
items: offers,
|
|
11043
|
-
rules
|
|
11987
|
+
rules: rulesFactory(chainId)
|
|
11044
11988
|
});
|
|
11045
11989
|
} };
|
|
11046
11990
|
}
|
|
@@ -11050,28 +11994,11 @@ function create(parameters) {
|
|
|
11050
11994
|
var Rules_exports = /* @__PURE__ */ __exportAll({
|
|
11051
11995
|
amountMutualExclusivity: () => amountMutualExclusivity,
|
|
11052
11996
|
callback: () => callback,
|
|
11053
|
-
chains: () => chains,
|
|
11054
11997
|
collateralToken: () => collateralToken,
|
|
11055
11998
|
loanToken: () => loanToken,
|
|
11056
11999
|
maturity: () => maturity,
|
|
11057
12000
|
oracle: () => oracle,
|
|
11058
|
-
sameMaker: () => sameMaker
|
|
11059
|
-
validity: () => validity
|
|
11060
|
-
});
|
|
11061
|
-
/**
|
|
11062
|
-
* set of rules to validate offers.
|
|
11063
|
-
*
|
|
11064
|
-
* @param _parameters - Validity parameters with chain and client
|
|
11065
|
-
* @returns Array of validation rules to evaluate against offers
|
|
11066
|
-
*/
|
|
11067
|
-
function validity(_parameters) {
|
|
11068
|
-
return [single("expiry", "Validates that offer has not expired", (offer) => {
|
|
11069
|
-
if (offer.expiry < Math.floor(Date.now() / 1e3)) return { message: "Expiry mismatch" };
|
|
11070
|
-
})];
|
|
11071
|
-
}
|
|
11072
|
-
const chains = ({ chains }) => single("chain_ids", `Validates that offer chain is one of: [${chains.map((c) => c.id).join(", ")}]`, (offer) => {
|
|
11073
|
-
const allowedChainIds = chains.map((c) => c.id);
|
|
11074
|
-
if (!allowedChainIds.some((id) => id === offer.chainId)) return { message: `Chain ID ${offer.chainId} is not in the allowed chains (${allowedChainIds.join(", ")})` };
|
|
12001
|
+
sameMaker: () => sameMaker
|
|
11075
12002
|
});
|
|
11076
12003
|
const maturity = ({ maturities }) => single("maturity", `Validates that offer maturity is one of: [${maturities.join(", ")}]`, (offer) => {
|
|
11077
12004
|
const allowedMaturities = maturities.map((m) => from$16(m));
|
|
@@ -11087,9 +12014,9 @@ const callback = ({ callbacks }) => single("callback", `Validates callbacks: buy
|
|
|
11087
12014
|
* @param assetsByChainId - Allowed loan tokens indexed by chain id.
|
|
11088
12015
|
* @returns The issue that was found. If the offer is valid, this will be undefined.
|
|
11089
12016
|
*/
|
|
11090
|
-
const loanToken = ({ assetsByChainId }) => single("loan_token", "Validates that offer loan token is in the allowed token list for the
|
|
11091
|
-
const allowedLoanTokens = assetsByChainId[
|
|
11092
|
-
if (!allowedLoanTokens || allowedLoanTokens.length === 0) return { message: `No allowed loan tokens for chain ${
|
|
12017
|
+
const loanToken = ({ assetsByChainId, chainId }) => single("loan_token", "Validates that offer loan token is in the allowed token list for the request chain", (offer) => {
|
|
12018
|
+
const allowedLoanTokens = assetsByChainId[chainId]?.map((asset) => asset.toLowerCase());
|
|
12019
|
+
if (!allowedLoanTokens || allowedLoanTokens.length === 0) return { message: `No allowed loan tokens for chain ${chainId}` };
|
|
11093
12020
|
if (!allowedLoanTokens.includes(offer.loanToken.toLowerCase())) return { message: "Loan token is not allowed" };
|
|
11094
12021
|
});
|
|
11095
12022
|
/**
|
|
@@ -11097,9 +12024,9 @@ const loanToken = ({ assetsByChainId }) => single("loan_token", "Validates that
|
|
|
11097
12024
|
* @param collateralAssetsByChainId - Allowed collateral tokens indexed by chain id.
|
|
11098
12025
|
* @returns The issue that was found. If the offer is valid, this will be undefined.
|
|
11099
12026
|
*/
|
|
11100
|
-
const collateralToken = ({ collateralAssetsByChainId }) => single("collateral_token", "Validates that offer collateral tokens are in the allowed token list for the
|
|
11101
|
-
const allowedCollateralTokens = collateralAssetsByChainId[
|
|
11102
|
-
if (allowedCollateralTokens.length === 0) return { message: `No allowed collateral tokens for chain ${
|
|
12027
|
+
const collateralToken = ({ collateralAssetsByChainId, chainId }) => single("collateral_token", "Validates that offer collateral tokens are in the allowed token list for the request chain", (offer) => {
|
|
12028
|
+
const allowedCollateralTokens = collateralAssetsByChainId[chainId]?.map((asset) => asset.toLowerCase()) ?? [];
|
|
12029
|
+
if (allowedCollateralTokens.length === 0) return { message: `No allowed collateral tokens for chain ${chainId}` };
|
|
11103
12030
|
if (offer.collaterals.length === 0) return { message: "At least one collateral token is required" };
|
|
11104
12031
|
if (offer.collaterals.some((collateral) => !allowedCollateralTokens.includes(collateral.asset.toLowerCase()))) return { message: "Collateral token is not allowed" };
|
|
11105
12032
|
});
|
|
@@ -11108,9 +12035,9 @@ const collateralToken = ({ collateralAssetsByChainId }) => single("collateral_to
|
|
|
11108
12035
|
* @param oraclesByChainId - Allowed oracles indexed by chain id.
|
|
11109
12036
|
* @returns The issue that was found. If the offer is valid, this will be undefined.
|
|
11110
12037
|
*/
|
|
11111
|
-
const oracle = ({ oraclesByChainId }) => single("oracle", "Validates that offer collateral oracles are in the allowed oracle list for the
|
|
11112
|
-
const allowedOracles = oraclesByChainId[
|
|
11113
|
-
if (!allowedOracles || allowedOracles.length === 0) return { message: `No allowed oracles for chain ${
|
|
12038
|
+
const oracle = ({ oraclesByChainId, chainId }) => single("oracle", "Validates that offer collateral oracles are in the allowed oracle list for the request chain", (offer) => {
|
|
12039
|
+
const allowedOracles = oraclesByChainId[chainId]?.map((oracle) => oracle.toLowerCase());
|
|
12040
|
+
if (!allowedOracles || allowedOracles.length === 0) return { message: `No allowed oracles for chain ${chainId}` };
|
|
11114
12041
|
if (offer.collaterals.some((collateral) => !allowedOracles.includes(collateral.oracle.toLowerCase()))) return { message: "Oracle is not allowed" };
|
|
11115
12042
|
});
|
|
11116
12043
|
/**
|
|
@@ -11142,11 +12069,12 @@ const amountMutualExclusivity = () => single("amount_mutual_exclusivity", "Valid
|
|
|
11142
12069
|
|
|
11143
12070
|
//#endregion
|
|
11144
12071
|
//#region src/gatekeeper/morphoRules.ts
|
|
11145
|
-
const morphoRules = (
|
|
12072
|
+
const morphoRules = (parameters) => {
|
|
12073
|
+
const { chains, chainId } = parameters;
|
|
11146
12074
|
const assetsByChainId = {};
|
|
11147
12075
|
const collateralAssetsByChainId = {};
|
|
11148
12076
|
const oraclesByChainId = {};
|
|
11149
|
-
for (const chain of chains
|
|
12077
|
+
for (const chain of chains) {
|
|
11150
12078
|
assetsByChainId[chain.id] = assets[chain.id.toString()] ?? [];
|
|
11151
12079
|
collateralAssetsByChainId[chain.id] = collateralAssets[chain.id.toString()] ?? [];
|
|
11152
12080
|
oraclesByChainId[chain.id] = oracles[chain.id.toString()] ?? [];
|
|
@@ -11154,15 +12082,23 @@ const morphoRules = (chains$3) => {
|
|
|
11154
12082
|
return [
|
|
11155
12083
|
sameMaker(),
|
|
11156
12084
|
amountMutualExclusivity(),
|
|
11157
|
-
chains({ chains: chains$3 }),
|
|
11158
12085
|
maturity({ maturities: [MaturityType.EndOfWeek, MaturityType.EndOfNextWeek] }),
|
|
11159
12086
|
callback({
|
|
11160
12087
|
callbacks: [Type$1.BuyWithEmptyCallback, Type$1.SellWithEmptyCallback],
|
|
11161
12088
|
allowedAddresses: []
|
|
11162
12089
|
}),
|
|
11163
|
-
loanToken({
|
|
11164
|
-
|
|
11165
|
-
|
|
12090
|
+
loanToken({
|
|
12091
|
+
assetsByChainId,
|
|
12092
|
+
chainId
|
|
12093
|
+
}),
|
|
12094
|
+
collateralToken({
|
|
12095
|
+
collateralAssetsByChainId,
|
|
12096
|
+
chainId
|
|
12097
|
+
}),
|
|
12098
|
+
oracle({
|
|
12099
|
+
oraclesByChainId,
|
|
12100
|
+
chainId
|
|
12101
|
+
})
|
|
11166
12102
|
];
|
|
11167
12103
|
};
|
|
11168
12104
|
|
|
@@ -11192,9 +12128,7 @@ function from(parameters) {
|
|
|
11192
12128
|
async function add(config, offers) {
|
|
11193
12129
|
if (!config.client.account) throw new WalletAccountNotSetError();
|
|
11194
12130
|
const tree = from$8(offers.map((o) => from$14(o)));
|
|
11195
|
-
const
|
|
11196
|
-
for (const offer of tree.offers) if (chainId !== offer.chainId) throw new ChainIdMismatchError(offer.chainId, chainId);
|
|
11197
|
-
const signatureDomain$1 = resolveSignatureDomain(config, chainId);
|
|
12131
|
+
const signatureDomain$1 = resolveSignatureDomain(config, await getChainId(config.client));
|
|
11198
12132
|
const signature = await config.client.signTypedData({
|
|
11199
12133
|
account: config.client.account,
|
|
11200
12134
|
domain: signatureDomain(signatureDomain$1),
|
|
@@ -11299,12 +12233,6 @@ var WalletAccountNotSetError = class extends BaseError {
|
|
|
11299
12233
|
var ViemClientError = class extends BaseError {
|
|
11300
12234
|
name = "Mempool.ViemClientError";
|
|
11301
12235
|
};
|
|
11302
|
-
var ChainIdMismatchError = class extends BaseError {
|
|
11303
|
-
name = "Mempool.ChainIdMismatchError";
|
|
11304
|
-
constructor(expected, actual) {
|
|
11305
|
-
super(`Chain ID mismatch. Offer chain ID is ${expected}, network chain ID is ${actual}.`);
|
|
11306
|
-
}
|
|
11307
|
-
};
|
|
11308
12236
|
const resolveSignatureDomain = (config, chainId) => {
|
|
11309
12237
|
const chain = config.client.chain;
|
|
11310
12238
|
const verifyingContract = config.morphoAddress ?? chain?.custom?.morpho?.address ?? getChain(chainId)?.custom.morpho.address;
|
|
@@ -11333,7 +12261,6 @@ function connect(parameters) {
|
|
|
11333
12261
|
//#endregion
|
|
11334
12262
|
//#region src/mempool/index.ts
|
|
11335
12263
|
var mempool_exports = /* @__PURE__ */ __exportAll({
|
|
11336
|
-
ChainIdMismatchError: () => ChainIdMismatchError,
|
|
11337
12264
|
MissingMorphoAddressError: () => MissingMorphoAddressError,
|
|
11338
12265
|
ViemClientError: () => ViemClientError,
|
|
11339
12266
|
WalletAccountNotSetError: () => WalletAccountNotSetError,
|
|
@@ -11451,6 +12378,12 @@ Object.defineProperty(exports, 'HealthController', {
|
|
|
11451
12378
|
return HealthController;
|
|
11452
12379
|
}
|
|
11453
12380
|
});
|
|
12381
|
+
Object.defineProperty(exports, 'Id', {
|
|
12382
|
+
enumerable: true,
|
|
12383
|
+
get: function () {
|
|
12384
|
+
return Id_exports;
|
|
12385
|
+
}
|
|
12386
|
+
});
|
|
11454
12387
|
Object.defineProperty(exports, 'Indexer', {
|
|
11455
12388
|
enumerable: true,
|
|
11456
12389
|
get: function () {
|