mev-inspect
Version:
A JS port of 'mev-inspect-py' optimised for ease of use.
189 lines • 6.19 kB
JavaScript
// eslint-disable-next-line import/no-extraneous-dependencies
import { JsonRpcProvider as LegacyJsonRpcProvider } from '@ethersproject/providers';
import { Provider as EthcallProvider } from 'ethcall';
import { getFactoryByAddress, getNftFactoryByAddress, getPoolByAddress, } from './classifier/index.js';
async function fetchPools(chainId, provider, logs) {
const pools = [];
const poolIds = new Set();
const callMap = {};
for (const log of logs) {
if (log.classifier.type !== 'swap') {
continue;
}
const id = getPoolId(log);
if (poolIds.has(id)) {
continue;
}
poolIds.add(id);
const logCalls = log.classifier.pool.getCalls(id);
callMap[log.logIndex] = logCalls;
}
const legacyProvider = new LegacyJsonRpcProvider(provider._getConnection().url);
const ethcallProvider = new EthcallProvider();
await ethcallProvider.init(legacyProvider);
const calls = Object.values(callMap).flat();
const results = await ethcallProvider.tryAll(calls);
let i = 0;
for (const log of logs) {
if (log.classifier.type !== 'swap') {
continue;
}
const logCalls = callMap[log.logIndex];
if (!logCalls) {
continue;
}
const result = [];
for (let j = 0; j < logCalls.length; j++) {
result.push(results[i + j]);
}
i += logCalls.length;
const poolData = log.classifier.pool.processCalls(result, log.address);
if (!poolData) {
continue;
}
const factory = getFactoryByAddress(chainId, log.classifier.protocol, poolData.factoryAddress);
if (!factory) {
continue;
}
const pool = {
address: getPoolAddress(log).toLowerCase(),
assets: poolData.assets,
factory,
};
pools.push(pool);
}
return pools;
}
async function fetchNftPools(chainId, provider, logs, block) {
const pools = [];
const poolAddresses = new Set();
const callMap = {};
for (const log of logs) {
if (log.classifier.type !== 'nft_swap') {
continue;
}
const address = log.address;
if (poolAddresses.has(address)) {
continue;
}
poolAddresses.add(address);
const logCalls = log.classifier.pool.getCalls(address);
callMap[log.logIndex] = logCalls;
}
const legacyProvider = new LegacyJsonRpcProvider(provider._getConnection().url);
const ethcallProvider = new EthcallProvider();
await ethcallProvider.init(legacyProvider);
const calls = Object.values(callMap).flat();
const results = await ethcallProvider.tryAll(calls, block);
let i = 0;
for (const log of logs) {
if (log.classifier.type !== 'nft_swap') {
continue;
}
const logCalls = callMap[log.logIndex];
if (!logCalls) {
continue;
}
const result = [];
for (let j = 0; j < logCalls.length; j++) {
result.push(results[i + j]);
}
i += logCalls.length;
const poolData = log.classifier.pool.processCalls(result, log.address, chainId);
if (!poolData) {
continue;
}
const factory = getNftFactoryByAddress(chainId, log.classifier.protocol, poolData.factoryAddress);
if (!factory) {
continue;
}
const pool = {
address: log.address.toLowerCase(),
factory,
asset: poolData.asset,
collection: poolData.collection,
metadata: poolData.metadata,
};
pools.push(pool);
}
return pools;
}
async function fetchMarkets(chainId, provider, logs) {
const markets = [];
const marketAddresses = new Set();
const callMap = {};
for (const log of logs) {
if (log.classifier.type !== 'repayment') {
continue;
}
const address = getMarketAddress(log);
if (marketAddresses.has(address)) {
continue;
}
marketAddresses.add(address);
const logCalls = log.classifier.market.getCalls(address);
callMap[log.logIndex] = logCalls;
}
const legacyProvider = new LegacyJsonRpcProvider(provider._getConnection().url);
const ethcallProvider = new EthcallProvider();
await ethcallProvider.init(legacyProvider);
const calls = Object.values(callMap).flat();
const results = await ethcallProvider.tryAll(calls);
let i = 0;
for (const log of logs) {
if (log.classifier.type !== 'repayment') {
continue;
}
const logCalls = callMap[log.logIndex];
if (!logCalls) {
continue;
}
const result = [];
for (let j = 0; j < logCalls.length; j++) {
result.push(results[i + j]);
}
i += logCalls.length;
const address = getMarketAddress(log);
const marketData = log.classifier.market.processCalls(chainId, address, result);
if (!marketData) {
continue;
}
const pool = getPoolByAddress(chainId, log.classifier.protocol, marketData.poolAddress);
if (!pool) {
continue;
}
const market = {
address: address.toLowerCase(),
asset: marketData.asset || address,
pool: {
label: pool.label,
address: marketData.poolAddress,
},
};
markets.push(market);
}
return markets;
}
function getPoolId(log) {
if (log.classifier.type !== 'swap') {
return '';
}
if (log.classifier.protocol === 'BalancerV2') {
return log.values.poolId;
}
return log.address;
}
function getPoolAddress(log) {
if (log.classifier.type !== 'swap') {
return '';
}
if (log.classifier.protocol === 'BalancerV2') {
return getPoolId(log).substring(0, 42);
}
return log.address;
}
function getMarketAddress(log) {
return log.address;
}
export { fetchPools, fetchNftPools, fetchMarkets };
//# sourceMappingURL=fetch.js.map